kenkoka/larajwt

JWT 认证和 Laravel API 项目的守卫

dev-master 2020-01-18 15:25 UTC

This package is auto-updated.

Last update: 2024-09-19 01:45:48 UTC


README

概述

KenKoKaLaraJWT 是一个 Laravel 扩展包,用于从用户生成 JWT(基于 JSON Web 的令牌),并为 Laravel 应用程序提供 JWT 守卫。

安装

通过 Composer 添加包

composer require kenkoka/larajwt

然后运行以下命令在您的 Laravel 配置目录中生成 jwt.php(包配置)

php artisan vendor:publish --tag=kenkokalarajwt-config

配置

要配置包,请打开您的 Laravel 配置目录中的 jwt.php 文件。此文件包含以下项目:

  • key: 签署令牌的秘密密钥,如果您留空,则使用项目密钥。

  • ttl: 令牌有效的时长,令牌将在该时间后过期(以秒为单位)。

  • issuer: 发行者声明。

  • audience: 受众声明。

  • model_safe: 如果您使用 KenKoKaLaraJwt 对不同模型有不同的认证,请将其设置为 true,它确保令牌属于守卫中定义的相关模型。

从用户生成 JWT

使用以下方法从用户或其他任何可验证实体(模型)生成 JWT

$jwt = JwtAuth::generateToken($user);

例如,您可以在登录过程中从用户生成 JWT 如下所示

$credential = [
    'email' => $request->input('email'),
    'password' => $request->input('password'),
];

if( Auth::guard('api')->attempt($credential) ) {
    $user = Auth::guard('api')->user();
    $jwt = JwtAuth::generateToken($user);
    // Return successfull sign in response with the generated jwt.
} else {
    // Return response for failed attempt...
}

如果您想在令牌中存储更多信息,如角色,您可以按此方式传递它们

$customClaims = ['role' => 'admin', 'foo' => 'bar'];
$jwt = JwtAuth::generateToken($user, $customClaims);

守卫

在您的 config/auth.php 中添加所需的守卫,例如使用 jwt 驱动程序

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

认证路由

配置 config/auth.php 中的守卫后,您可以使用定义的守卫保护路由。

在我们的示例中,我们可以这样保护路由

Route::group(['middleware' => 'auth:api'], function () {
    // Routes...
});

您的客户端必须在请求中发送头信息 Authorization: Bearer <token>

认证用户

要检索您的应用程序中的当前用户及其信息(例如控制器),您可以这样做

// To get current user
$user = Auth::guard('api')->user();
$user = Auth::guard('api')->getUser();

// To get current user id
$user = Auth::guard('api')->id();

// Is current user guest
$user = Auth::guard('api')->guest();

// To get current token
$jwt = Auth::guard('api')->getToken();

// To get current token claims
$claims = Auth::guard('api')->getClaims();

// To get a sepcific claim from current token
$role = Auth::guard('api')->getClaim('role');

// Logout current user (JWT will be cached in blacklist and NOT valid in next requests).
Auth::guard('api')->logout();

// Logout current user (but it will be VALID next reuqests).
// It clears caches so user will be fetched and filters will be executed again in next request.
Auth::guard('api')->logout(false);

由于 LaraJwt 缓存用户获取,它可以在不接触数据库的情况下验证用户。

手动检索用户您可能需要手动从生成的 JWT 中检索用户,不用担心!只需这样做即可

$user = JwtAuth::retrieveUser($jwt);

它使用默认的用户提供程序来获取用户,如果您使用不同的提供程序,您可以将其作为第二个参数传递给方法

$admin = JwtAuth::retrieveUser($jwt, 'admin');

手动检索 JWT 声明您甚至可以更进一步,手动检索 JWT 声明,这也已考虑在内。

$claims = JwtAuth::retrieveClaims($jwt);

所述方法返回以下结构的关联数组声明

[
    'sub' => '666',
    'iss' => 'Your app name',
    'aud' => 'Your app audience',
    // ...
]

缓存

KenKokaLaraJwt 缓存检索用户的过程,因此第一次成功认证后,它会记住 jwt,直到配置中设置的 ttl,您可以通过此方法清除此缓存以强制 LaraJwt 重新运行过滤器或从数据库重新获取用户模型

JwtAuth::clearCache($user);

您可以将用户模型(Authenticable)或其主键传递给 clearCache 方法。

过滤器

过滤器是可运行的闭包,将在解析令牌和获取用户模型之后调用。

例如,如果您考虑了用户的一个布尔属性,如 is_active,您可能希望在认证后检查其值,如果为 false,则抛出异常或以某种方式更改 LaraJwt 的正常流程,使其看起来认证失败。

您可以注册任意数量的过滤器,LaraJwt 在认证后逐个运行它们。

AuthServiceProvider 看起来是注册钩子的好地方。

class AuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $jwtAuth = $this->app->make(JwtAuthInterface::class);
        // Check if user is active or not
        $jwtAuth->registerFilter(function (User $user) {
            if ($user->is_active == true) {
                return $user;
            } else {
                return null;
            }
        });
    }
}

registerFilter函数接收一个闭包,该闭包有一个参数用于获取认证用户。如果没有问题,它应该返回用户;如果你想使认证失败,它可以返回null。

注销和JWT失效 如上例所示,你可以使用以下方法注销用户:

Auth::guard('api')->logout();

它接受一个布尔参数,默认值为true,将jwt放入缓存的黑名单中,这样在后续请求中该token将无效。但你可以传递false使其只注销当前用户并清除缓存。

你也可以通过JwtAuth外观和jti声明以这种方式使token无效:

JwtAuth::invalidate($jti);

异常

异常类:LaraJwtConfiguringException

异常信息:KenKoKaLaraJwt配置未找到。如果你没有发布包配置(在安装部分中提到),将抛出此异常。

JWT与存储令牌

你可能考虑简单的数据库存储令牌作为JWT认证的替代方案,所以我们为你提供了一些差异和比较。

缺点

HTTP开销更大,生成的令牌更长。强制注销更复杂、更棘手(LaraJwt为你处理)。

优点

不需要数据库列来存储生成的令牌。如果你只需要用户ID,则无需接触数据库。如果需要缓存用户获取(LaraJwt为你处理),则数据库接触更少。