ホームページ > バックエンド開発 > PHPチュートリアル > Laravel 5 で JWT (Json Web Token) を使用して API ベースのユーザー認証を実装する

Laravel 5 で JWT (Json Web Token) を使用して API ベースのユーザー認証を実装する

WBOY
リリース: 2016-06-20 12:34:14
オリジナル
2891 人が閲覧しました

JavaScript フロントエンド テクノロジが普及している現在、通常はフロントエンド呼び出しを提供するためにバックグラウンドで API を構築するだけでよく、バックエンドは設計のみです。フロントエンド モバイル アプリによって呼び出されます。ユーザー認証は Web アプリケーションの重要な部分です。API ベースのユーザー認証には、OAuth 2.0 と JWT (JSON Web Token) という 2 つの最適なソリューションがあります。

1. JWT の定義と構成

JWT (JSON Web Token) は非常に軽量な仕様です。この仕様により、JWT を使用してユーザーとサーバー間で安全で信頼できる情報を渡すことができるようになります。

JWT は実際には文字列であり、ヘッダー、ペイロード、署名の 3 つの部分で構成されます。

ペイロード

まず、ユーザー認証操作を JSON オブジェクトとして記述します。将来この JWT を受信するサーバーがこの JWT を理解するのに役立つ他の情報が追加されます。

{    "sub": "1",    "iss": "http://localhost:8000/auth/login",    "iat": 1451888119,    "exp": 1454516119,    "nbf": 1451888119,    "jti": "37c107e4609ddbcc9c096ea5ee76c667"}
ログイン後にコピー

ここの最初の 6 フィールドは、JWT 標準によって定義されています。

  • sub: この JWT の対象となるユーザー
  • iss: この JWT の発行者
  • iat(issued at): トークンがいつ発行されたか
  • exp(expires): トークンの有効期限はいつですか?
  • nbf (not before): この期限までにトークンを受信して​​処理することはできません。
  • jti: JWT ID は、 Web トークンの一意の識別子

これらの定義は標準規格に記載されています。

上記の JSON オブジェクトを Base64 エンコードして、次の文字列を取得します。

eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4ODExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
ログイン後にコピー

この文字列を JWT ペイロードと呼びます。

Node.js を使用する場合は、Node.js パッケージのbase64url を使用して次の文字列を取得できます。

var base64url = require('base64url')var header = {    "from_user": "B",    "target_user": "A"}console.log(base64url(JSON.stringify(header)))
ログイン後にコピー

注: Base64 はエンコーディングです。元の形式に戻すことができます。これは暗号化プロセスではありません。

ヘッダー

JWT にはヘッダーも必要です。ヘッダーは、JWT のタイプや使用されるアルゴリズムなど、JWT に関する最も基本的な情報を記述するために使用されます。サインなどこれは、JSON オブジェクトとして表すこともできます:

{  "typ": "JWT",  "alg": "HS256"}
ログイン後にコピー

ここでは、これが JWT であり、使用する署名アルゴリズム (後述) が HS256 アルゴリズムであることを示します。

これも Base64 でエンコードされている必要があり、後続の文字列が JWT のヘッダーになります。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
ログイン後にコピー

Signature (署名)

Connect上の 2 つのエンコードされた文字列をピリオドで (先頭から) 形成します:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4ODExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
ログイン後にコピー

最後に、上記の文字を結合します 文字列は HS256 アルゴリズムを使用して暗号化されます。暗号化するときは、キー (秘密) も指定する必要があります:

HMACSHA256(    base64UrlEncode(header) + "." +    base64UrlEncode(payload),    secret)
ログイン後にコピー

この方法で、暗号化されたコンテンツを取得できます:

wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
ログイン後にコピー

この部分は署名とも呼ばれます。

最後に、署名のこの部分も署名された文字列の後に結合され、完全な JWT が得られます。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4ODExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ.wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
ログイン後にコピー

2. JWT を Laravel 5 に統合します

インストール

Composer を使用して jwt 拡張パッケージをインストールします:

composer require tymon/jwt-auth 0.5.*
ログイン後にコピー

設定

インストールが完了したら、対応するサービスプロバイダーを config/app.php に登録する必要があります:

Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class
ログイン後にコピー

次に、使用する必要がある対応するファサードを登録します:

'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class
ログイン後にコピー

次に、対応する設定ファイルを公開します:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
ログイン後にコピー

最終的に生成されたキー:

php artisan jwt:generate
ログイン後にコピー

.env ファイルに追加する場合は、.env に JWT_SECRET フィールドを作成して実行しますキーコマンドを再度生成します。

config/jwt.php で、次のオプションを設定できます:

  • ttl: トークンの有効期間 (分)
  • refresh_ttl: トークンのリフレッシュ時間 (分) )
  • algo: トークン署名アルゴリズム
  • user: ユーザー モデルを指す名前空間パス
  • 識別子: トークンのサブからユーザーを取得するために使用されます
  • require_claims : トークンのペイロードに含める必要があるオプション。そうでない場合は、TokenInvalidException 例外がスローされます。
  • blacklist_enabled: このオプションが false に設定されている場合、トークンを無効にすることはできません。トークンを更新しても、以前のトークンは残ります。 有効な
  • プロバイダー: さまざまなタスクを完了するための特定の実装。必要に応じて書き換えることができます。
    • ユーザー - Providers.user: ユーザーの取得の実装サブ
    • JWT に基づいています - Providers.jwt: 暗号化/復号化トークン
    • 認証 - Providers.auth: 証明書/ID によって認証されたユーザーを取得します
    • ストレージ - Providers.storage:有効期限が切れるまでトークンを保存します

トークンの作成

ユーザー トークンを作成する最も一般的な方法は、ログインによるユーザー認証を実装することです。成功すると、対応するユーザーのトークンが返されます。ここでは、AuthenticateController があると仮定します:

use JWTAuth;use Tymon\JWTAuth\Exceptions\JWTException;class AuthenticateController extends Controller{    public function authenticate(Request $request)    {        // grab credentials from the request        $credentials = $request->only('email', 'password');        try {            // attempt to verify the credentials and create a token for the user            if (! $token = JWTAuth::attempt($credentials)) {                return response()->json(['error' => 'invalid_credentials'], 401);            }        } catch (JWTException $e) {            // something went wrong whilst attempting to encode the token            return response()->json(['error' => 'could_not_create_token'], 500);        }        // all good so return the token        return response()->json(compact('token'));    }}
ログイン後にコピー

場合によっては、ユーザー オブジェクト インスタンスを通じて直接トークンを作成することもできます:

// grab some user$user = User::first();$token = JWTAuth::fromUser($user);
ログイン後にコピー

さらに、TymonJWTAuthPayloadFactory インスタンスを使用することもできます。 (または JWTFactory ファサード) 任意のデータに基づいてトークンを作成します:

$customClaims = ['foo' => 'bar', 'baz' => 'bob'];$payload = JWTFactory::make($customClaims);$token = JWTAuth::encode($payload);
ログイン後にコピー

メソッドチェーンを使用することもできます:

// add a custom claim with a key of `foo` and a value of ['bar' => 'baz']$payload = JWTFactory::sub(123)->aud('foo')->foo(['bar' => 'baz'])->make();$token = JWTAuth::encode($payload);
ログイン後にコピー

用户认证

用户登录成功之后,下一步就是发送一个包含token的请求来获取用户信息。

要通过http发送一个需要认证通过的请求,需要设置Authorization头:

Authorization: Bearer {yourtokenhere}
ログイン後にコピー

如果用户名/密码没有进行base64编码那么Apache似乎会摒弃Authorization头,要修复这一问题你可以添加如下代码到Apache配置文件:

RewriteEngine OnRewriteCond %{HTTP:Authorization} ^(.*)RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
ログイン後にコピー

或者将token信息包含到URL中:

http://api.mysite.com/me?token={yourtokenhere}
ログイン後にコピー

要从请求中获取token,你可以这么做:

// this will set the token on the objectJWTAuth::parseToken();// and you can continue to chain methods$user = JWTAuth::parseToken()->authenticate();
ログイン後にコピー

要获取该token值,你可以这么调用:

$token = JWTAuth::getToken();
ログイン後にコピー

如果token被设置则会返回,否则会尝试使用方法从请求中解析token,如果token未被设置或不能解析最终返回false。

当然如果需要的话你还可以手动设置token:

JWTAuth::setToken('foo.bar.baz');
ログイン後にコピー

从Token中获取认证用户:

// somewhere in your controllerpublic function getAuthenticatedUser(){    try {        if (! $user = JWTAuth::parseToken()->authenticate()) {            return response()->json(['user_not_found'], 404);        }    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {        return response()->json(['token_expired'], $e->getStatusCode());    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {        return response()->json(['token_invalid'], $e->getStatusCode());    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {        return response()->json(['token_absent'], $e->getStatusCode());    }    // the token is valid and we have found the user via the sub claim    return response()->json(compact('user'));}
ログイン後にコピー

jwt-auth扩展还提供了两个中间件 GetUserFromToken 和 RefreshToken ,前者用于在请求头和参数中检查是否包含token,并尝试对其解码,后者会再次从请求中解析token,并顺序刷新token(同时废弃老的token)并将其作为下一个响应的一部分。要使用这两个中间件,需要到 app/Http/Kernel.php 下的 $routeMiddleware 属性中注册它们:

protected $routeMiddleware = [    ...    'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',    'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',];
ログイン後にコピー

JWT让用户认证变得简单和安全,token会被保存到本地的 storage/web 或Cookie中,使用JWT,基于API的用户认证将不再困难。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート