ホームページ  >  記事  >  PHPフレームワーク  >  Laravel jwtマルチテーブル検証分離

Laravel jwtマルチテーブル検証分離

步履不停
步履不停オリジナル
2019-07-03 14:18:283608ブラウズ

Laravel jwtマルチテーブル検証分離

なぜ分離する必要があるのか​​

同じlaravelプロジェクトに複数の端末(モバイル端末、管理端末など)があり、すべてユーザーにjwtを使用する必要がある場合検証では、複数のユーザーテーブルがある場合(通常は存在します)、トークンの分離を行う必要があります。そうしないと、モバイル側のトークンも管理側に要求でき、ユーザーが権限を超えてしまうという問題が発生します。

この問題が発生する理由は、laravel の jwt トークンがデフォルトでデータテーブルの主キーの値のみを格納し、どのテーブルであるかを区別しないためです。したがって、トークンに含まれる ID がユーザー テーブルに存在する限り、不正な検証が行われてしまいます。

laravel の jwt トークンの元の外観を見てみましょう:

{
    "iss": "http://your-request-url",
    "iat": 1558668215,
    "exp": 1645068215,
    "nbf": 1558668215,
    "jti": "XakIDuG7K0jeWGDi",
    "sub": 1,
    "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd"
}

データを運ぶサブフィールドはサブフィールドで、他のフィールドは jwt の検証フィールドです。

sub の値が 1 であることがわかるだけで、それがどのテーブルまたはバリデーターに属しているかは示されません。このトークンが検証ミドルウェアを通過すると、さまざまなガードを使用して、対応するテーブル ID 1 を持つユーザーを取得できます (ガードについて詳しくは、laravel のドキュメントを確認してください)。

解決策

ユーザーのオーバーリーチの問題を解決するには、トークンにカスタム フィールドを追加して、どのテーブルまたはバリデータがトークンを生成したかを区別し、それを検証する独自のミドルウェアを作成するだけです。カスタムフィールドは私たちの期待と一致しています。

カスタム情報をトークンに追加する

jwt 検証を使用するには、ユーザー モデルが JWTSubject インターフェイスを実装する必要があることがわかっています (コードは 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 [];
    }
}

これら 2 つの実装されたメソッドの機能を見てみましょう:

  • getJWTIdentifier: jwt ステートメントに保存される識別子を取得します。実際には、主キー フィールドを返す必要があります。ユーザー テーブルを識別する名前です。返される内容は次のとおりです。主キー 'id' です。
  • getJWTCustomClaims: jwt 宣言に追加されるカスタム キーと値のペアを含む配列を返します。空の配列が返されます。ここではカスタム情報は追加されていません。

次に、getJWTCustomClaims メソッドを実装するユーザー モデルにカスタム情報を追加できます。

管理者モデル:

/**
 * 额外在 JWT 载荷中增加的自定义内容
 *
 * @return array
 */
public function getJWTCustomClaims()
{
    return ['role' => 'admin'];
}

モバイル ユーザー モデル:

/**
 * 额外在 JWT 载荷中增加的自定义内容
 *
 * @return array
 */
public function getJWTCustomClaims()
{
    return ['role' => 'user'];
}

ここにユーザー ID としてロール名が追加されます。

管理者によって生成されたトークンは次のようになります:

{
    "iss": "http://your-request-url",
    "iat": 1558668215,
    "exp": 1645068215,
    "nbf": 1558668215,
    "jti": "XakIDuG7K0jeWGDi",
    "sub": 1,
    "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd",
    "role": "admin"
}

モバイル ユーザーによって生成されたトークンは次のようになります:

{
    "iss": "http://your-request-url",
    "iat": 1558668215,
    "exp": 1645068215,
    "nbf": 1558668215,
    "jti": "XakIDuG7K0jeWGDi",
    "sub": 1,
    "prv": "92d5e8eb1b38ccd11476896c19b0e44512b2aacd",
    "role": "user"
}

追加された役割フィールドは、ユーザー モデルに対応します。

次に、ミドルウェアを自分で書きます。トークンを解析した後、それが必要な役割であるかどうかを判断します。一致する場合はパスし、一致しない場合は 401 を報告します。

jwt ロール検証ミドルウェアを作成します

これはグローバルに使用可能なミドルウェアです (ユーザー検証ミドルウェアの前に使用することをお勧めします):

<?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);
    }
}

jwt ロール検証検証ミドルウェアを登録します

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,
    ];

jwt ロール検証ミドルウェアを使用します

次に、ユーザー検証が必要なルートを追加します。ミドルウェアをグループに追加します。

Route::group([
    'middleware' => ['jwt.role:admin', 'jwt.auth'],
], function ($router) {
    // 管理员验证路由
    // ...
});

Route::group([
    'middleware' => ['jwt.role:user', 'jwt.auth'],
], function ($router) {
    // 移动端用户验证路由
    // ...
});

これで、jwt の複数テーブルのユーザー検証の分離が完了しました。

Laravel 関連の技術記事の詳細については、Laravel チュートリアル 列にアクセスして学習してください。

以上がLaravel jwtマルチテーブル検証分離の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。