Quand le même projet Laravel a plusieurs terminaux (terminal mobile, terminal de gestion...) et que tous doivent utiliser jwt pour la vérification des utilisateurs, s'il y a plusieurs tables d'utilisateurs (il y en a généralement), l'isolation du jeton doit être effectuée, sinon il y aura un problème selon lequel le jeton du côté mobile peut également demander le côté gestion, ce qui amènera l'utilisateur à dépasser son autorité.
La raison pour laquelle ce problème se produit est que le jeton jwt de Laravel stocke uniquement la valeur de la clé primaire de la table de données par défaut et ne distingue pas de quelle table il s'agit. Ainsi, tant que l'ID contenu dans le jeton existe dans votre table utilisateur, cela entraînera une vérification non autorisée.
Jetons un coup d'œil à l'apparence originale du jeton jwt de Laravel :
{ "iss": "http://your-request-url", "iat": 1558668215, "exp": 1645068215, "nbf": 1558668215, "jti": "XakIDuG7K0jeWGDi", "sub": 1, "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd" }
Le sous-champ qui transporte les données est le sous-champ, et les autres champs sont les champs de vérification de jwt.
Nous voyons seulement que la valeur de sub est 1, et cela n'indique pas à quelle table ou validateur il appartient. Lorsque ce jeton passe votre middleware de vérification, vous pouvez utiliser différents gardes pour obtenir l'utilisateur avec l'identifiant de table correspondant 1 (pour en savoir plus sur le garde, veuillez consulter la documentation de Laravel).
Pour résoudre le problème de la portée excessive des utilisateurs, il nous suffit d'apporter nos champs personnalisés sur le jeton pour distinguer quelle table ou quel validateur l'a généré, puis d'écrire votre propre middleware pour vérifier que nos champs personnalisés correspondent à nos attentes.
Nous savons que pour utiliser la vérification jwt, le modèle utilisateur doit implémenter l'interface JWTSubject (le code est extrait du document jwt) :
<?php namespace App; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { use Notifiable; // Rest omitted for brevity /** * Get the identifier that will be stored in the subject claim of the JWT. * * @return mixed */ public function getJWTIdentifier() { return $this->getKey(); } /** * Return a key value array, containing any custom claims to be added to the JWT. * * @return array */ public function getJWTCustomClaims() { return []; } }
On peut jeter un œil aux fonctions de ces deux méthodes implémentées :
Ensuite, nous pouvons ajouter nos informations personnalisées au modèle utilisateur qui implémente la méthode getJWTCustomClaims.
Modèle d'administrateur :
/** * 额外在 JWT 载荷中增加的自定义内容 * * @return array */ public function getJWTCustomClaims() { return ['role' => 'admin']; }
Modèle d'utilisateur mobile :
/** * 额外在 JWT 载荷中增加的自定义内容 * * @return array */ public function getJWTCustomClaims() { return ['role' => 'user']; }
Un nom de rôle est ajouté ici comme identifiant d'utilisateur.
Le token généré par l'administrateur ressemblera à ceci :
{ "iss": "http://your-request-url", "iat": 1558668215, "exp": 1645068215, "nbf": 1558668215, "jti": "XakIDuG7K0jeWGDi", "sub": 1, "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd", "role": "admin" }
Le token généré par l'utilisateur mobile ressemblera à ceci :
{ "iss": "http://your-request-url", "iat": 1558668215, "exp": 1645068215, "nbf": 1558668215, "jti": "XakIDuG7K0jeWGDi", "sub": 1, "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd", "role": "user" }
On voit qu'il y en a un plus de nous-mêmes ici Le champ de rôle ajouté correspond à notre modèle d'utilisateur.
Ensuite, nous écrivons nous-mêmes un middleware. Après avoir analysé le jeton, nous déterminerons si c'est le rôle que nous voulons. S'il correspond, il passera. S'il ne correspond pas, il signalera 401.
Voici un middleware utilisable globalement (il est recommandé de l'utiliser avant le middleware de vérification de l'utilisateur) :
<?php /** * Created by PhpStorm. * User: wlalala * Date: 2019-04-17 * Time: 13:55 */ namespace App\Http\Middleware; use Closure; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Http\Middleware\BaseMiddleware; class JWTRoleAuth extends BaseMiddleware { /** * Handle an incoming request. * * @param $request * @param Closure $next * @param null $role * @return mixed */ public function handle($request, Closure $next, $role = null) { try { // 解析token角色 $token_role = $this->auth->parseToken()->getClaim('role'); } catch (JWTException $e) { /** * token解析失败,说明请求中没有可用的token。 * 为了可以全局使用(不需要token的请求也可通过),这里让请求继续。 * 因为这个中间件的责职只是校验token里的角色。 */ return $next($request); } // 判断token角色。 if ($token_role != $role) { throw new UnauthorizedHttpException('jwt-auth', 'User role error'); } return $next($request); } }
Enregistrez le middleware dans app/Http/Kernel.php :
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ // ...省略 ... // 多表jwt验证校验 'jwt.role' => \App\Http\Middleware\JWTRoleAuth::class, ];
Ensuite, ajoutez la route qui nécessite la vérification de l'utilisateur Ajoutez notre middleware au groupe :
Route::group([ 'middleware' => ['jwt.role:admin', 'jwt.auth'], ], function ($router) { // 管理员验证路由 // ... }); Route::group([ 'middleware' => ['jwt.role:user', 'jwt.auth'], ], function ($router) { // 移动端用户验证路由 // ... });
Ceci complète l'isolement de la vérification des utilisateurs multi-tables JWT.
Pour plus d'articles techniques liés à Laravel, veuillez visiter la colonne Tutoriel Laravel pour apprendre !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!