raphaelbsr / yii2-jwt-tools
在 Yii Framework 2 项目中配置 JWT 认证和验证的简单方法
Requires
- php: >=7.1
- firebase/php-jwt: ^5.2
- yiisoft/yii2: ^2.0
Requires (Dev)
- codedungeon/phpunit-result-printer: ^0.27.0
- friendsofphp/php-cs-fixer: ^2.15
- phpunit/phpunit: ^8.4
- squizlabs/php_codesniffer: *
README
JWT Tools 是一个工具箱,可以帮助您配置使用 JWT 令牌进行身份验证。这不仅包括身份验证,还包括签名验证和著名的密钥。
我最大的动力是,因为我没有看到一种简单的方式来设置一个简单的 JWT 验证和一些辅助函数。我总是需要将整个代码复制粘贴到新项目中。
按照以下步骤在您的项目中安装和设置。
安装
安装此扩展的首选方法是通过 composer。
要安装,请运行
$ php composer.phar require dersonsena/yii2-jwt-tools
或添加
"dersonsena/yii2-jwt-tools": "^1.0"
到您的 composer.json 文件的 require 部分。
使用
配置文件
让我们确保一些应用程序设置是正确的。打开您的 config/web.php 并进行如下设置
'components' => [ // ... 'request' => [ 'enableCookieValidation' => false, ], 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => false, 'enableSession' => false, 'loginUrl' => null ], // ...
控制器
在您的控制器类中,在 behaviors() 方法中注册 JWTSignatureBehavior 和 HttpBearerAuth 行为,如下所示
use yii\rest\Controller; class YourCuteController extends Controller { public function behaviors() { $behaviors = parent::behaviors(); $behaviors['jwtValidator'] = [ 'class' => JWTSignatureBehavior::class, 'secretKey' => Yii::$app->params['jwt']['secret'], 'except' => ['login'] // it's doesn't run in login action ]; $behaviors['authenticator'] = [ 'class' => HttpBearerAuth::class, 'except' => ['login'] // it's doesn't run in login action ]; return $behaviors; } }
注意:在此示例中,我使用
Yii::$app->params['jwt']['secret']来存储我的 JWT 密钥,但我非常喜欢 .env 文件,这些信息可以存储在那里
JWTSignatureBehavior 将验证通过 Authorization HTTP 标头发送的 JWT 令牌。如果您的令牌存在问题,将抛出以下异常之一
-
UnauthorizedHttpException,消息为
您的请求没有提供授权令牌。如果 HTTP 标头不存在或令牌为空或为 null。 -
UnauthorizedHttpException,消息为
身份验证令牌已过期。如果令牌已过期。 -
UnauthorizedHttpException,消息为
令牌签名无效。如果令牌签名无效。
如果您需要更改 HTTP 标头名称(老实说,我看不到这种情况),可以更改此设置,如下所示
class YourCuteController extends Controller { // ... public function behaviors() { $behaviors['jwtValidator'] = [ 'class' => JWTSignatureBehavior::class, 'secretKey' => Yii::$app->params['jwt']['secret'], 'headerName' => 'Auth' ]; } // ... }
在您的登录操作中,您需要创建一个 JWT 令牌以发送响应。创建令牌非常简单,请参阅以下内容
class YourCuteController extends Controller { // ... public function behaviors() { $behaviors['jwtValidator'] = [ 'class' => JWTSignatureBehavior::class, 'secretKey' => Yii::$app->params['jwt']['secret'], 'headerName' => 'Auth' ]; } public function actionLogin() { // validation stuff // find user $token = JWTTools::build(Yii::$app->params['jwt']['secret']) ->withModel($user, ['name', 'email', 'group']) ->getJWT(); return ['success' => true, 'token' => $token]; } // ... }
模型身份类
到这一点,我们知道令牌是有效的,我们可以对其进行解码以验证用户。
我在这里使用 app/models/User 作为我的用户身份,因此,让我们实现 IdentityInterface 接口的 findIdentityByAccessToken() 方法
namespace app\models; use yii\db\ActiveRecord; use yii\web\IdentityInterface; class User extends ActiveRecord implements IdentityInterface { // ... public static function findIdentity($id) { return static::findOne($id); } public function getId() { return $this->id; } public function getAuthKey() { // we don't need to implement this method } public function validateAuthKey($authKey) { // we don't need to implement this method } public static function findIdentityByAccessToken($token, $type = null) { $decodedToken = JWTTools::build(Yii::$app->params['jwt']['secret']) ->decodeToken($token); return static::findOne(['id' => $decodedToken->sub]); } }
如果一切正常,到这一点,您可以使用有效的 JWT 令牌进行身份验证。
演示
生成令牌
您可以使用 JWTTools 方法在项目中执行特定操作。以下是一些示例
use Dersonsena\JWTTools\JWTTools; $jwtTools = JWTTools::build('my-secret-key'); $token = $jwtTools->getJWT(); $payload = $jwtTools->getPayload()->getData(); var_dump($token); print_r($payload);
此代码将返回类似以下内容
string(248) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6ImJlMTgzOTQ4YjJmNjkzZSJ9.eyJzdWIiOiJiZTE4Mzk0OGIyZjY5M2UiLCJpc3MiOiIiLCJhdWQiOiIiLCJpYXQiOjE1ODkxMzEzNjIsImV4cCI6MTU4OTEzNDk2MiwianRpIjoiNTM4NTRiMGQ5MzFkMGVkIn0.-JDBkID1oJ7anC_JLg68AJxbKGK-5ubA83zZlDZYYso"
Array
(
[sub] => 9c65241853de774
[iss] =>
[aud] =>
[iat] => 1589129672
[exp] => 1589133272
[jti] => a0a98e2364d2721
)
注意:
->getPayload()返回一个 JWTPayload 实例。
使用 Active Record 生成 Token
您可以使用 withModel() 方法将 Active Record 属性插入到载荷中,如下所示
use Dersonsena\JWTTools\JWTTools; $user = app\models\User::findOne(2); $payload = JWTTools::build('my-secret-key'); ->withModel($user, ['id', 'name', 'email']) ->getPayload() ->getData(); print_r($payload);
此代码将返回类似以下内容
Array
(
[sub] => 10 <~~~~
[iss] =>
[aud] =>
[iat] => 1589130028
[exp] => 1589133628
[jti] => 7aba5b7666d7868
[id] => 10 <~~~~
[name] => Kilderson Sena <~~~~
[email] => email@email.com.br <~~~~
)
根据 RFC7519 指示,sub 属性会自动重写为 $model->getPrimaryKey() 的值。
更改 JWT 属性
您可以通过在第二个方法参数中添加一个数组来更改 JWT 属性(例如 iss,aud 等),如下所示
use Dersonsena\JWTTools\JWTTools; $payload = JWTTools::build('my-secret-key', [ 'algorithm' => 'ES256', 'expiration' => 1589069866, //<~~ It will generate the exp property automatically 'iss' => 'yourdomain.com', 'aud' => 'yourdomain.com', ]);
作者
- Kilderson Sena - 初始工作 - Yii Academy
请参阅参与此项目的 贡献者列表。
贡献
欢迎提交拉取请求。对于重大更改,请先打开一个问题以讨论您想更改的内容。
请确保根据需要更新测试。