abublihi / laravel-external-jwt-guard
这是一个使用外部JWT进行用户身份验证的Laravel自定义认证保护器
Requires
- php: ^8.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0
- lcobucci/clock: ^2.0|^3.0
- lcobucci/jwt: ^4.2|^5.0
Requires (Dev)
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0
README
此包提供了一个简单的自定义认证保护器,用于Laravel,使用由OAuth服务器提供的或任何使用JWT的任何类型的SSO提供的JWT。以下图表示明了流程。
安装
您可以通过composer安装此包
composer require abublihi/laravel-external-jwt-guard
发布配置文件 externaljwtguard.php
php artisan vendor:publish --provider="Abublihi\LaravelExternalJwtGuard\LaravelExternalJwtGuardServiceProvider" --tag config
使用方法
此包非常简单,但在定制方面也非常强大。在安装和发布配置之后,您首先需要配置您的 default
授权服务器,
注意:此包允许您添加多个授权服务器,但对于大多数使用场景,您只需要一个授权服务器。
配置您的授权服务器
<?php return [ 'authorization_servers' => [ 'default' => [ /* Identification settings */ 'id_claim' => env('JWT_GUARD_ID_CLAIM', 'sub'), 'roles_claim' => env('JWT_GUARD_ROLES_CLAIM', 'roles'), 'id_attribute' => env('JWT_GUARD_ID_ATTRIBUTE', 'id'), /* Creation setting */ 'create_user' => env('JWT_GUARD_CREATE_USER', false), 'create_user_action_class' => null, /* Validation settings */ 'issuer' => '', 'validate_issuer' => true, 'public_key' => env('JWT_GUARD_AUTH_SERVER_PUBLIC_KEY'), // if RSA, make sure it's start with -----BEGIN PUBLIC KEY----- and ends with -----END PUBLIC KEY----- 'signing_algorithm' => env('JWT_GUARD_AUTH_SIGN_ALG', 'RS256'), ], // you could add as many as you want of the authorization servers by duplicating the configurations above ^^ 'admin' => [ 'id_claim' => 'sub', ..... ] ], ];
请访问配置文件 config/externaljwtguard.php
,配置分为三个主要部分
- 身份设置
- 创建设置(可选)
- 验证设置
身份设置
首先我们将介绍 身份设置
的配置,正如其名,身份设置
是允许此包通过使用JWT声明来识别用户的配置。
注意:请确保这些配置正确。
注意:id_attribute是您的系统中的,此包使用它来识别已认证的用户,例如,如果您已将保护器配置为配置了用户模型的提供者,则此包将查找id_attribute并将其与JWT中的id_claim进行匹配
'id_claim' => env('JWT_GUARD_ID_CLAIM', 'sub'), 'roles_claim' => env('JWT_GUARD_ROLES_CLAIM', 'roles'), // not yet used 'id_attribute' => env('JWT_GUARD_ID_ATTRIBUTE', 'id'), // in your database (e.g. users table)
创建设置(可选)
创建设置用于配置如果系统不存在时如何创建用户,您可以禁用此功能,我们鼓励禁用此功能。
注意:您必须自己实现创建用户的操作,该操作应实现接口
Abublihi\LaravelExternalJwtGuard\Interfaces\CreateUserActionInterface
'create_user' => env('JWT_GUARD_CREATE_USER', false), // you can define your own action by implementing the interface Abublihi\LaravelExternalJwtGuard\Interfaces\CreateUserActionInterface 'create_user_action_class' => null,
验证设置
'issuer' => 'https://example.com', 'validate_issuer' => true, 'public_key' => env('JWT_GUARD_AUTH_SERVER_PUBLIC_KEY'), // if RSA, make sure it's start with -----BEGIN PUBLIC KEY----- and ends with -----END PUBLIC KEY----- 'signing_algorithm' => env('JWT_GUARD_AUTH_SIGN_ALG', 'RS256'),
保护器配置
在配置我们的授权服务器后,接下来我们需要在 config/auth.php
中配置我们的保护器
在Guards中,您可以添加/修改您想要使用JWT作为认证保护器的保护器,通过将驱动设置为 external-jwt-auth
。我们有一个自定义属性,即 auth_server_key
,它指示授权服务器密钥,默认设置为 default
。
'guards' => [ . . 'api-jwt' => [ 'driver' => 'external-jwt-auth', // <-- here you have to set the drive to `external-jwt-auth` 'provider' => 'users', ], // you can set the authorization server key as seen below 'api-jwt-admin' => [ 'driver' => 'external-jwt-auth', // <-- here you have to set the drive to `external-jwt-auth` 'provider' => 'users', 'auth_server_key' => 'admin', // the authorization key for admin ], . . ],
测试您的配置
在例如 routes/api.php
中添加路由
Route::middleware('auth:api-jwt')->group(function() { Route::get('user', function(){ return request()->user(); // <-- will return the user which is configured }); });
JWT角色中间件
此包还附带一个检查JWT(用户)角色的角色中间件,您应首先使用配置文件 roles_claim
配置正确的角色声明,该声明应是一个 数组 的角色。要使用中间件,您有两个选项
- 在
app/Http/Kernel.php
中定义一个 别名 - 直接使用中间件而不使用别名
在kernel中定义中间件别名
转到 app/Http/Kernel.php
并添加以下行
注意:别名名称可以是任何名称
protected $middlewareAliases = [ // ... 'jwt-role' => \Abublihi\LaravelExternalJwtGuard\Middleware\CheckJwtRoles::class ];
在路由中使用中间件
Route::group(['middleware' => ['auth:api-jwt' 'jwt-role:manager']], function () { // this will allow any jwt with the role `manager` });
您可以使用 |(管道)字符指定多个角色,该字符被视为 OR
Route::group(['middleware' => ['auth:api-jwt' 'jwt-role:manager|super-admin']], function () { // this will allow any jwt with the role `manager` or `super-admin` });
直接在kernel上使用中间件而不定义它
use Abublihi\LaravelExternalJwtGuard\Middleware\CheckJwtRoles; Route::group(['middleware' => ['auth:api-jwt' CheckJwtRoles::class.':manager']], function () { // this will allow any jwt with the role `manager` });
您可以使用 |(管道)字符指定多个角色,该字符被视为 OR
// with OR operator Route::group(['middleware' => ['auth:api-jwt' CheckJwtRoles::class.':manager|super-admin']], function () { // this will allow any jwt with the role `manager` });
示例JWT与角色声明
{ "iss": "http://example.com", "aud": "http://example.org", "sub": "2", "jti": "4f1g23a12aa", "iat": 1707071173.863238, "nbf": 1707071113.863238, "exp": 1707074773.863238, "uid": "2", "roles": [ "manager", "super-admin" ] }
测试
ActingAs 功能
本包提供actingAs函数,帮助您测试受external-jwt-auth
守卫保护的路由,要使用它,只需在测试中使用\Abublihi\LaravelExternalJwtGuard\Traits\ActingAs
特性,然后调用actingAsExternalJwt
函数,这将生成配置(私有和公开密钥)和有效的令牌,然后使用$this->withHeader(..)
将其添加到请求头。
class SampleTest extends TestCase { use DatabaseMigrations, \Abublihi\LaravelExternalJwtGuard\Traits\ActingAs; /** * @test * @define-route usesAuthRoutes */ function test_it_returns_authenticated_user_by_jwt() { $user = User::factory()->create(); $this->actingAsExternalJwt($user); } }
如果您想生成带有一些自定义声明或无效或过期的令牌,可以将Abublihi\LaravelExternalJwtGuard\Support\FakeTokenIssuer
实例传递给actingAsExternalJwt
。
如果您想生成无效或过期的令牌,例如,可以将Abublihi\LaravelExternalJwtGuard\Support\FakeTokenIssuer
实例传递给actingAsExternalJwt
。
use Abublihi\LaravelExternalJwtGuard\Support\FakeTokenIssuer; class SampleTest extends TestCase { use DatabaseMigrations, \Abublihi\LaravelExternalJwtGuard\Traits\ActingAs; /** * @test * @define-route usesAuthRoutes */ function test_it_returns_authenticated_when_with_role_admin() { $user = User::factory()->create(); $this->actingAsExternalJwt( FakeTokenIssuer:user($user) ->withClaims([ 'roles' => [ 'admin' ] ]) ); } /** * @test * @define-route usesAuthRoutes */ function test_it_returns_authenticated_when_with_custom_claim_employee_name() { $user = User::factory()->create(); $this->actingAsExternalJwt( FakeTokenIssuer:user($user) ->withClaims([ 'employee_name' => 'Mohammed Abdullah', 'other_info' => [ 'info 1', 'info 2' ] ]) ); } /** * @test * @define-route usesAuthRoutes */ function test_it_returns_unauthenticated_when_invaild() { $user = User::factory()->create(); $this->actingAsExternalJwt( FakeTokenIssuer:user($user) ->asInvalid() ); } /** * @test * @define-route usesAuthRoutes */ function test_it_returns_unauthenticated_when_expired() { $user = User::factory()->create(); $this->actingAsExternalJwt( FakeTokenIssuer:user($user) ->asExpired() ); } }
生成的代码和配置将设置为default
授权服务器,您可以通过传递授权服务器密钥给第二个参数来更改它。
class SampleTest extends TestCase { use DatabaseMigrations, \Abublihi\LaravelExternalJwtGuard\Traits\ActingAs; /** * @test * @define-route usesAuthRoutes */ function test_it_returns_authenticated_user_by_jwt() { $user = User::factory()->create(); $this->actingAsExternalJwt($user, 'admin'); // this will set the authorization server key to `admin` } }
测试包
composer test
变更日志
有关最近更改的更多信息,请参阅CHANGELOG。
贡献
有关详细信息,请参阅CONTRIBUTING。
安全性
如果您发现任何与安全相关的问题,请通过电子邮件abublihi@gmail.com而不是使用问题跟踪器。
致谢
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。