sprocketbox/laravel-jwt

Laravel 的无缝 JWT 实现

v1.5.0 2020-09-09 16:21 UTC

This package is auto-updated.

Last update: 2024-09-10 01:16:45 UTC


README

Latest Stable Version Latest Unstable Version License Scrutinizer Code Quality

Laravel JWT 提供了一个无缝的 JWT (JSON Web Tokens) 实现,该实现直接与 Laravel 的认证库集成,允许进行无状态的 API 认证。

目录

安装

要安装此软件包,请运行以下命令。

composer require sprocketbox/laravel-jwt

此软件包使用自动发现来注册服务提供者,但如果您想手动完成,服务提供者是

Sprocketbox\JWT\JWTServiceProvider

配置

不需要额外的配置文件,但在配置 config/auth.php 中的守卫时有一些额外的选项。

这是一个 JWT 守卫的示例配置。

'api' => [
    'driver'   => 'jwt',
    'provider' => 'users',
    'key'      => env('JWT_KEY_API'),
    'signer'   => Lcobucci\JWT\Signer\Hmac\Sha256::class,
    'ttl'      => 'P1M',
],

快速配置

如果您不想深入研究所有额外的部分,可以通过以下方式创建一个非常简单的 JWT 守卫配置

  • 将驱动器更改为 jwt
  • 添加 'key' => env('JWT_KEY_GUARD'), 其中 GUARD 是您认证守卫的名称
  • 运行 php artisan jwt:generate guard 其中 guard 是您认证守卫的名称
  • 请确保将环境变量复制到您的 .env.example 文件中,但不要复制值

驱动器

如果您想使用 JWT 驱动器,只需将 driver 选项设置为 jwt

密钥

如果您希望您的令牌被签名,您至少必须使用 key 选项提供密钥。由于默认签名使用 SHA256 HMAC,我建议使用 64 个字符的密钥。

最好将此密钥放在您的 env 文件中,例如 JWT_KEY 或类似名称。

签名者

默认情况下,此软件包将使用 SHA256 HMAC 创建签名,但如果您想更改它,可以将 signer 选项设置为有效签名的类名。

默认为 Lcobucci\JWT\Signer\Hmac\Sha256,但 Lcobucci\JWT\Signer 命名空间 中还有其他选项。如果您想保持默认设置,可以省略此选项。

TTL

默认情况下,此软件包将 TTL (总生存时间) 设置为 1 个月,或更准确地说 P1M。如果您想更改此设置,可以将 ttl 配置值设置为有效的 时间间隔规范

自定义生成

如果您想自己生成令牌,可以提供自定义生成器如下所示

Auth::guard('api')->setTokenGenerator(function (\Illuminate\Contracts\Auth\Authenticatable $user, \Sprocketbox\JWT\JWTGuard $guard) {
    return $instanceOfBuilder;
});

生成器必须返回一个 Lcobucci\JWT\Builder 实例。

自定义验证

如果您想为您的令牌提供自定义验证,可以提供如下所示

Auth::guard('api')->setTokenValidator(function (\Lcobucci\JWT\Token $token, \Sprocketbox\JWT\JWTGuard $guard) {
    return $validationState;
});

如果验证失败,您必须返回 false。任何其他返回类型,包括 null,都将被视为通过。

自定义令牌签名生成

在某些情况下,您可能会发现配置中的静态签名方法和密钥不足。如果是这种情况,您可以提供以下覆盖方法

Auth::guard('api')->setTokenSigner(function (\Sprocketbox\JWT\JWTGuard $guard): array {
    return [
        new config('auth.guards.api.signer'), 
        new \Lcobucci\JWT\Signer\Key(config('auth.guards.api.key'))
    ];
});

此方法必须返回一个数组,其中第一个索引为签名者,第二个索引为密钥。

生成密钥

您可以通过运行带有守卫名称的jwt:generate命令来为每个守卫生成一个密钥。该命令的签名如下

jwt:generate {guard}
    {--length : The length of the key, defaults to 32}
    {--show : Display the key instead of modifying files}
    {--force : Force the operation to run when in production}

使用

此包的功能与Laravels会话身份验证几乎相同,但有几点例外。

提供令牌

令牌以载体令牌的方式加载,因此您必须在HTTP授权头中将其提供为载体令牌。

Authorization: Bearer TOKEN_HERE

如果您将true作为attempt()的第二个参数传递,则令牌将由cookie自动提供,从而无需手动传递令牌。

获取令牌

Auth::attempt($credentials)方法缺少第二个参数(记住我),并且返回的不是布尔值,而是返回一个Lcobucci\JWT\Token实例。将该对象转换为字符串将给出实际的JWT令牌。

如果您想获取当前使用的令牌,即当前已认证的令牌,可以在守卫上调用token()方法,就像调用user()一样。

示例

以下代码可作为示例

$input = $request->only('email', 'password');
$token = Auth::guard('api')->attempt($input);

if ($token !== null) {
    return response()->json(['token' => (string) $token]);
}

return response()->json(null, 401);

避免 XSS

如果您将true作为attempt()的第二个参数传递,守卫将创建一个只通过HTTP(不可通过JavaScript访问)的cookie。这将防止您需要在浏览器的localStorage中存储令牌。

为了确保cookie被添加到响应中,您需要将以下中间件添加到路由中。

Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class

将其添加到api组中是有意义的。尽管技术上不是必需的,但我建议您还添加以下中间件来加密cookie。

App\Http\Middleware\EncryptCookies::class

还建议在使用此方法时简单地返回204响应,以便令牌数据不会输出到任何地方。

事件

登录和认证事件与会话守卫一样调用。

令牌

默认情况下,令牌生成有一些偏见,但这是因为这是此包的初始版本。

以下内容介绍了如何填充声明。

  • 由/发行者(iss)设置为config('app.url')
  • 允许的/受众(aud)也设置为config('app.url')
  • 识别/ID(jti)是与令牌一起生成的UUID4
  • 发行于(iat)设置为当前时间戳
  • 过期于(exp)设置为当前时间戳+ttl的值(默认为P1M
  • 相关/主题(sub)设置为Authenticatable::getAuthIdentifier()的值

令牌使用lcobucci/jwt包生成。

未来

我希望能将以下内容添加到此包的后续版本中。我已尝试在此列出所有内容,作为某种路线图。

  • 支持HTTP Only cookie(XSS)
  • 自定义令牌生成
  • 自定义令牌验证
  • 自定义令牌签名
  • 使用数据库记录jtiaudexp以黑名单和吊销令牌
  • 提供生成JWT的认证脚手架