ユーザログイン認証の実装(token)

8054 ワード

1.JWT定義とその構成
JWT(JSON Web Token)は非常に軽量な仕様です.この仕様では、JWTを使用して、ユーザーとサーバの間で安全で信頼性の高い情報を伝達できます.
JWTは実際には文字列であり、ヘッダ、荷重、署名の3つの部分から構成されています.荷重(Payload)
まず,ユーザ認証の動作を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):         token
exp(expires): token      
nbf(not before):token             
jti:JWT ID web token      

これらの定義は、標準で見つけることができます.
上のJSONオブジェクトをbase 64符号化すると、次の文字列が得られます.
eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
この文字列をJWTのPayload(荷重)と呼びます.
Node.jsを使用する場合は、Node.jsのパッケージbase 64 urlを使用してこの文字列を取得できます.
var base64url = require(‘base64url’) var header = { “from_user”: “B”, “target_user”: “A” } console.log(base64url(JSON.stringify(header)))
 :Base64     ,    ,               。          。

ヘッド
JWTには、JWTに関する最も基本的な情報、例えばそのタイプや署名に使用されるアルゴリズムなどを記述するヘッダが必要である.これは、JSONオブジェクトとして表すこともできる.
{ “typ”: “JWT”, “alg”: “HS256” }
ここでは、これはJWTであり、我々が使用する署名アルゴリズム(後述)はHS 256アルゴリズムであることを説明する.
これに対してもBase 64符号化を行い、その後の文字列はJWTのHeader(ヘッダ):
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
署名(署名)
上の2つの符号化された文字列を句点で接続すると、次のようになります.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ
最後に、上につづった文字列をHS 256アルゴリズムで暗号化します.暗号化するには、鍵(secret)も必要です.
HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret )
これにより、暗号化されたコンテンツが得られます.
wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4
この部分はサインとも呼ばれます.
最後にこの部分の署名も署名された文字列の後ろにつなぎ合わせて、私たちは完全なJWTを得ました:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ.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:token   (  )
refresh_ttl:  token  (  )
algo:token    
user:  User         
identifier:   token sub     
require_claims:     token payload    ,     TokenInvalidException  
blacklist_enabled:         false,         token,       token,   token    
providers:           ,             
    User —— providers.user:  sub       
    JWT —— providers.jwt:  /  token
    Authentication —— providers.auth:    /ID      
    Storage —— providers.storage:  token      

Tokenの作成
ユーザーtokenを作成する最も一般的な方法は、ログインによってユーザー認証を実現し、成功すれば対応するユーザーのtokenを返すことです.ここではAuthenticateControllerがあるとします.
use JWTAuth; use Tymon\JWTAuth\Exceptions\JWTException;
class AuthenticateController extends Controller { public function authenticate(Request request)      {          // grab credentials from the 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'));
}

}
ユーザー・オブジェクト・インスタンスからtokenを直接作成することもできます.
//grab some user user=User::first(); u s e r = U s e r::f i r s t ( ) ; token = JWTAuth::fromUser($user);
さらに、TymonJWTAuthPayloadFactoryインスタンス(またはJWTFactoryフェース)を使用して、任意のデータに基づいてtokenを作成することもできます.
customClaims=[‘foo′=>‘bar′,‘baz′=>‘bob′]; c u s t o m C l a i m s = [ ‘ f o o ′ => ‘ b a r ′ , ‘ b a z ′ => ‘ b o b ′ ] ; payload = JWTFactory::make( customClaims); c u s t o m C l a i m s ) ; 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(); p a y l o a d = J W T F a c t o r y::s u b ( 123 ) − > a u d ( ‘ f o o ′ ) − > f o o ( [ ‘ b a r ′ => ‘ b a z ′ ] ) − > m a k e ( ) ; token = JWTAuth::encode($payload);
ユーザ認証
ユーザーログインに成功したら、次はtokenを含むリクエストを送信してユーザー情報を取得します.
httpで認証が必要なリクエストを送信するには、Authorizationヘッダを設定する必要があります.
Authorization: Bearer {yourtokenhere}
ユーザー名/パスワードがbase 64符号化されていない場合、ApacheはAuthorizationヘッダを破棄するようです.この問題を解決するには、次のコードをApacheプロファイルに追加します.
RewriteEngine On RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
または、token情報をURLに含めます.
http://api.mysite.com/me?token={yourtokenhere}
リクエストからtokenを取得するには、次のようにします.
//this will set the token on the object JWTAuth::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 controller public function getAuthenticatedUser() { try { if (! user = JWTAuth::parseToken()->authenticate()) {              return response()->json([‘user_not_found’], 404);          }      } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException 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->getStatusCode());      } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException e) { return response()->json([‘token_invalid’], e->getStatusCode());      } catch (Tymon\JWTAuth\Exceptions\JWTException 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拡張では、要求ヘッダとパラメータにtokenが含まれているかどうかを確認し、復号しようとする2つのミドルウェアGetUserFromTokenとRefreshTokenも提供されます.後者は、要求からtokenを再解析し、古いtokenを破棄しながらtokenを順次リフレッシュします.次の応答の一部として使用します.この2つのミドルウェアを使用するには、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ベースのユーザー認証は難しくなくなります.