仓库源文站点原文


title: "Laravel Passport OAuth2 实践" date: 2022-03-28T17:30:00+08:00 tags: ["laravel", "oauth2", "passport"] draft: false

toc: true

引言

最近在搞 OAuth2 Service 相关功能,踩了很多坑,打算记录分享一下。

这篇文章主要讲 OAuth2 的实现,以及 Laravel Passport 的使用。

介绍 OAuth2

简单来讲 OAuth 2.0 就是一个行业的标准授权协议。目的是为了给第三方应用颁发一个有时效性的访问令牌,以便第三方应用能够访问被授权的资源,我们常见场景有第三方登录。

<!--more-->

流程

我们以 miro 网站为例,简单记录了一下使用流程:

  1. 用户使用 Facebook 联合登录。
  2. 如果之后用户未登录 Facebook,则网站跳转到 Facebook 登录页面
  3. Facebook 询问用户是否同意授权其在 Facebook 的资料,一般都是 email 和名字。
  4. 用户点击同意之后,miro 可以获取用户 Facebook 的资料。

角色

名词解释

协议流程

OAuth2 Abstract Flow

OAuth2 的主要授权流程是:

  1. 客户端请求资源所有者授权
  2. 资源所有者授权给客户端
  3. 客户端向授权服务器申请访问令牌
  4. 授权服务器授权给客户端有效的访问令牌
  5. 客户端使用访问令牌访问资源服务器请求资源
  6. 资源服务器验证令牌并返回资源

授权类型

OAuth2 有四种授权方式获取资源:

Laravel 使用 OAuth2 Server

搭建

Laravel 官方提供了一个组件 Laravel Passport,可以让你快速的搭建一个标准的 OAuth2 服务。

使用方式这里就多说了,多看看官方文档就可以了。

API 使用方式

这才是本篇文章想要分享的重点。官方文档的使用说明没有提到如何通过 API 的方式使用,但是目前前后端分离的开发方式已经成为主流了,所以我就自己去摸索了,网上能找到的资料也很少,基本是没找到。

配置参数

修改 config/auth.php 文件,修改之后的配置:

<?php

return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],
    'password_timeout' => 10800,
],

重点说明:

配置路由

修改 app/Providers/AuthServiceProvider.php 文件,修改之后的配置:

<?php

namespace App\Providers;

use App\Enums\Scope;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    public function boot()
    {
        $this->registerPolicies();
        if (!$this->app->routesAreCached()) {
            Passport::ignoreCsrfToken();
            Passport::routes(null, ['prefix' => 'api/v1/oauth', 'middleware' => ['api']]);
        }

        Passport::tokensCan(Scope::descriptions());
    }
}

重点说明:

使用 Openid

如果你也有「给不同的 Client 分配不同的 Openid 」的需求的话,可以看看这个 - 《laravel passport 加密 jwt 格式的 access_token 中的 sub(user_id) 字段》

结合上面的文章,使用 hashids加密的时候加上 client_id 就可以实现了以上需求了。

最后

OAuth2 概念其实挺多的,但是其应用也是非常广泛的。之所有搞这么复杂还是为了安全性。不同的使用场景选择不同的授权模式。

另外我也找到了一个在线体验 OAuth2 的网站 - OAuth 2.0 Playground 可以方便你加速理解。

资料