sprocketbox / laravel-jwt
Laravel 的无缝 JWT 实现
Requires
- php: ^7.3
- laravel/framework: ^6.0 || ^7.0 || ^8.0
- lcobucci/jwt: ^3.0
- ramsey/uuid: ^3.7
This package is auto-updated.
Last update: 2024-09-10 01:16:45 UTC
README
- Laravel: 6
- PHP: 7.2+
- 许可证: MIT
- 作者: Ollie Read
- 作者主页: https://sprocketbox.io
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)
- 自定义令牌生成
- 自定义令牌验证
- 自定义令牌签名
- 使用数据库记录
jti
、aud
和exp
以黑名单和吊销令牌 - 提供生成JWT的认证脚手架