ホームページ >PHPフレームワーク >Laravel >laravel8におけるdingoとjwt認証の解析

laravel8におけるdingoとjwt認証の解析

藏色散人
藏色散人転載
2021-05-27 15:33:103140ブラウズ

laravel の次のチュートリアル コラムでは、laravel8 での dingo と jwt 認証について紹介します。

1 dingo とは

dingo api パッケージは、laravel および lumen 用に提供される Restful ツール パッケージであり、jwt コンポーネントと連携してユーザー認証を迅速に完了し、同時にデータと実行中のプロセスで生成された例外をキャッチし、対応する応答を行うことができます。

主な機能:

    Router Version ルーティングのバージョン管理
  1. http 例外例外処理
  2. レスポンス変換変換レスポンスフォーマット
1 dingo のインストール
composer を介して laravel ルート ディレクトリに dingo 拡張パッケージをインストールします。具体的なコマンドは次のとおりです:

composer require dingo/api
次のコマンドを使用して、API 設定ファイルを設定ファイルに公開します:

php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
2 dingo の設定
dingo の API 設定レターについては、.env ファイルで設定できます

# dingo
# API_SUBTYPE —— 项目的简称;
API_SUBTYPE=lms
# API_PREFIX —— 与 API_DOMAIN 二选一,路由的前缀,例如设置为 api
API_PREFIX=api
# 定义版本
API_VERSION=v1
# 是否开启调试模式
API_DEBUG=true
dingo の詳細な設定については、関連ドキュメントを確認してください。 : https://learnku.com/docs/dingo-api/2.0.0/Configuration/1444

2 JWT

jwt の正式名は JSON Web Tokens です。 jwt を使用して、ユーザーとサーバーの間で安全で信頼できる情報を転送できる軽量仕様です。主な使用シナリオは次のとおりです: 認証とデータ交換##​​

#1 JWT

をインストールする laravel のコンポーザーを通じて jwt を実行しますルート ディレクトリ 拡張機能パッケージをインストールするための特定のコマンドは次のとおりです:
composer require tymon/jwt-auth

次のコマンドを使用して、API 構成ファイルを構成ファイルに公開します:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

2 Configure JWT

.env ファイルで jwt 暗号化キーを生成します。具体的なコマンドは次のとおりです:
php artisan jwt:secret

Modify config/api.phpconfiguration

'auth' => [
    'jwt' => 'Dingo\Api\Auth\Provider\JWT',
],

Modify config/auth.phpconfiguration

'defaults' => [
        #注:这里修改改了默认的配置,默认是web
        'guard' => 'api',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

jwt の詳細 構成については、関連ドキュメントを参照してください: https://jwt-auth.readthedocs.io/en/develop/

3 関連コードのデモ

Createトークンの有効期限を更新するための RefreshToken ミドルウェア

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class RefreshToken extends BaseMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // 检查此次请求中是否带有 token,如果没有则抛出异常。
        $this->checkForToken($request);

        // 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException  异常
        try {
            // 检测用户的登录状态,如果正常则通过
            if ($this->auth->parseToken()->authenticate()) {
                return $next($request);
            }
            throw new UnauthorizedHttpException('jwt-auth', '未登录');
        } catch (TokenExpiredException $exception) {
            // 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
            try {
                // 刷新用户的 token
                $token = $this->auth->refresh();
                // 使用一次性登录以保证此次请求的成功
                Auth::guard('api')
                    ->onceUsingId($this->auth->manager()
                        ->getPayloadFactory()
                        ->buildClaimsCollection()
                        ->toPlainArray()['sub']);
            } catch (JWTException $exception) {
                // 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
                throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
            }
        }

        // 在响应头中返回新的 token
        return $this->setAuthenticationHeader($next($request), $token);
    }
}

ユーザー モデルは、getJWTIdentifier() と getJWTCustomClaims() の 2 つのメソッドを実装する必要があります

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

    public $table = "user";

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        &#39;name&#39;, &#39;email&#39;, &#39;password&#39;,&#39;phone&#39;,&#39;status&#39;,&#39;create_time&#39;,&#39;addr_id&#39;
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        &#39;password&#39;, &#39;remember_token&#39;,
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
//        &#39;email_verified_at&#39; => 'datetime',
    ];

    /**
     * 指示是否自动维护时间戳
     *
     * @var bool
     */
    public $timestamps = false;

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
    public function getJWTCustomClaims()
    {
        return [];
    }
}
?>

認証およびその他の関連操作用の UserController を作成します

<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\User;
use Dingo\Api\Routing\Helpers;
use Illuminate\Http\Request;

class UserController extends Controller
{
    use Helpers;

    public function __construct()
    {
       //除去token验证的方法
       $this->middleware('refresh.token', [
            'except' => [
                'login',
            ],
        ]);
    }


    /**用户登录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|void
     */
    public function login(Request $request)
    {
        $phone = $request->get('phone');

        $user = User::where('phone', $phone)->first();

//        //attempt貌似无法验证其他字段,如需用其他字段鉴权使用login()
//        $credentials = request(['name','password']);
//        if (!$token = auth()->attempt($credentials)) {
//            return response()->json(['error' => 'Unauthorized'], 401);
//        }

        //只要是user实例就可以通过login鉴权
        if (! $token = auth()->login($user)) {
            return response()->json([
                "restful" => false,
                "message" => "账号错误",
            ]);
        }

        //获取用户信息
        $user = $this->user();
        $key = "user::info::".$user->id;
        //Redis缓存用户信息3600秒
        Redis::set($key,serialize($user->original),"EX",3600);

        return $this->respondWithToken($token);
    }

    /**获取用户
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function user()
    {
        return response()->json(auth()->user());
    }

    /**用户退出
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth()->logout();

        return response()->json(["message" => "退出成功"]);
    }

    /**用户登录状态刷新
     * Refresh a token.
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth()->refresh());
    }

    /**返回值
     * @param $token
     * @return array
     */
    protected function respondWithToken($token)
    {
        return [
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'restful' => true
        ];
    }
}

以上がlaravel8におけるdingoとjwt認証の解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjianshu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。