同域名应用可以使用框架自带的登录页面(基于Session)实现登录,登录成功后使用laravel_token(基于Cookie)实现 API 请求认证。

安装 & 初始化

composer require laravel/passport
php artisan migrate
# 执行 passport 的安装过程
php artisan passport:install
  1. 在 storage 目录下生成 oauth-private.keyoauth-public.key,分别为 OAuth 服务的私钥和公钥,用于安全令牌的加密解密。
  2. oauth_clients 数据表中初始化两条记录,相当于注册两个客户端应用,一个用于密码授权令牌认证,一个用于私人访问令牌认证。

修改模型类

use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    # 该 Trait 中包含了授权令牌与客户端的相关方法
    use HasApiTokens, Notifiable;
    ...
}

注册 API 认证相关路由

use Laravel\Passport\Passport;

public function boot()
{
    // API 认证路由注册
    Passport::routes();
}

默认提供的路由控制器位于 \Laravel\Passport\Http\Controllers 命名空间下,并且路由前缀为 /oauth

修改配置文件

修改配置文件 config/auth.php,将 API 认证驱动由 token 修改为 passport

'guards' => [
    ...
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

单页面应用 API 认证

如果 API 认证只用于客户端 JavaScript 与后端接口的交互,比如同域名应用,没必要走复杂的跳转授权流程,可以在 App\Http\Kernel$middlewareGroups 中新增一个 CreateFreshApiToken 中间件来实现:

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

该中间件注册在 web 路由中,当用户通过 Web 页面登录后会在 Cookie 中设置一个 Token,后续客户端发送请求时就会在 Cookie 中自动带上这个 Token。

在访问需要认证的 API 接口时,会走 auth:api 认证中间件,因为我们在配置文件 config/auth.php 中配置的 API 认证驱动是 passport,在 Laravel 框架底层,根据中间件传入的参数 api ,针对 API 接口认证会通过 Laravel\Passport\Guards\TokenGuard 获取认证信息:

public function user(Request $request)
{
    if ($request->bearerToken()) {
        return $this->authenticateViaBearerToken($request);
    } elseif ($request->cookie(Passport::cookie())) {
        return $this->authenticateViaCookie($request);
    }
}

如果请求头中包含 Bearer Authentication 请求头,则获取对应的请求头 Token 信息,否则从 Cookie 中获取名为 laravel_token 的 Token 信息,由于在保存这个 Token 的时候包含了用户ID,所以可以提取其中的用户 ID 从数据库获取用户数据并返回,从而完成用户认证判断和信息获取。

测试单页面应用 API 认证

Laravel 框架默认在 routes/api.php 中提供了一个认证 API 路由,可以基于这个路由进行测试:

// 为了方便测试,先忽略 CSRF 校验
\Laravel\Passport\Passport::$ignoreCsrfToken = true;

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

在浏览器中访问这个 API 接口,由于没有登录,会跳转到登录表单。登录完成后,就可以通过 http://blog.test/api/user 获取用户信息了。

通过浏览器开发者工具,在「Network」中查看请求 Cookie 数据就可以看到 laravel_token 的信息。


小伍
139 声望4 粉丝

引用和评论

0 条评论