laravel - json web token

Json web token

簡稱JWT,一個健壯令牌標準-RFC7519
JWT由三部分組成:php

  1. headerhtml

  2. payloadlaravel

  3. VERIFY SIGNATUREgit

header&payload用base64編碼,中間用.隔開,重要的是VERIFY SIGNATURE,使用HMAC SHA-256算法生成摘要,具體爲github

#僞代碼
HMACSHA256(
  base64encode(header) + "." + base64Encode(payload) + '.' +secret
)

php中hs256算法:web

//algo指定爲sha256,數據放data,screat爲key
string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )

secret存服務器端,別泄露了。具體瞭解可參考:JWT.io算法


Laravel + jwt

這裏Token生成的算法及驗證就肯定下來,和laravel 5.2 搭配使用以下:
119b9350-5cae-11e5-850b-c941cac60b32.pngapache

基本配置

1.安裝:composer require tymon/jwt-auth 0.5.*
2.config/app.php中:json

  1. provider增長跨域

    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class
  2. aliases 增長

    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class

3.發佈相應配置文件

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

執行完命令後在config/下會新增jwt配置文件jwt.php:

//file:jwt.php
    /*
    |--------------------------------------------------------------------------
    | JWT Authentication Secret (進行加密算法的時候的secret,這裏32位)
    |--------------------------------------------------------------------------
    */

    'secret' => env('JWT_SECRET', 'ZD23ADFVKSKSDFSDJFKDFDFVsafaa12a'),

    /*
    |--------------------------------------------------------------------------
    | JWT time to live (token有效期,單位分鐘)
    |--------------------------------------------------------------------------
    | Defaults to 1 hour
    | 1 hour = 60 minutes
    */

    'ttl' => 60,

    /*
    |--------------------------------------------------------------------------
    | Refresh time to live (刷新token時間,單位分鐘)
    |--------------------------------------------------------------------------
    | Defaults to 2 weeks
    | 2 weeks = 20160 minute
    */

    'refresh_ttl' => 20160,

    /*
    |--------------------------------------------------------------------------
    | JWT hashing algorithm (token簽名算法)
    |--------------------------------------------------------------------------
    */

    'algo' => 'HS256',

    /*
    |--------------------------------------------------------------------------
    | User Model namespace (指向User模型的命名空間路徑)
    |--------------------------------------------------------------------------
    */

    'user' => 'App\Models\User',

    /*
    |--------------------------------------------------------------------------
    | User identifier (用於從token的sub中獲取用戶)
    |--------------------------------------------------------------------------
    |
    */

    'identifier' => 'id',

    /*
    |--------------------------------------------------------------------------
    | Required Claims (必須出如今token的payload中的選項,不然會拋出TokenInvalidException異常) 
    |--------------------------------------------------------------------------
    |
    */

    'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'],

    /*
    |--------------------------------------------------------------------------
    | Blacklist Enabled (若是該選項被設置爲false,那麼咱們將不能廢止token,即便咱們刷新了token,前一個token仍然有效)
    |--------------------------------------------------------------------------
    */

    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),

    /*
    |--------------------------------------------------------------------------
    | Providers (完成各類任務的具體實現,有需求的狀況寫可重寫)
    |--------------------------------------------------------------------------
    */

    'providers' => [


        'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',

        'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter',

        'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter',

        'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter',

    ],

];

4.最後生成密鑰secret,寫入config/jwt.phpJWT_SECRET的value

php artisan jwt:generate

生成token

1.控制器中建立token,使用orm獲取用戶對象:

$userObj = User::where('email',$username)->first();
$res['token'] = JWTAuth::fromUser($userObj);

2.客戶端獲取到token,可寫入localstorage,正常會話週期每次請求帶上,token放入header中:Authorization : Bearer {token},這裏的bearer有持票人的意思,token兩邊的{}必須有。

在apache下會有header被丟棄的狀況,apache下得寫配置

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

驗證

由於接口多,放到路由羣組用中間件過濾(中間件姿式如使用不正確請指出):
1.執行php artisan make:middleware verifyToken,在app\Http\Middleware\verifyToken.php會生成verifyToken前置中間件,填充代碼以下:

namespace App\Http\Middleware;

use Closure;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class verifyToken
{
    /**
     * 請求前置中間件
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try {
            if (!JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (TokenExpiredException $e) {
            //toke失效,response code可自定義
            return response()->json(['token_expired'], 405);
        } catch (TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        return $next($request);
    }
}

2.app\Http\Kernel.php中在routeMiddleware處註冊中間件,

'verifyToken' => 'App\Http\Middleware\verifyToken'

3.路由羣組中使用:

//羣組中中間件能夠用多個,用數組傳入便可
//這裏的fetchResponse是後置中間件,用於包裝供cors跨域的幾個header
Route::group(['middleware' => ['fetchResponse','verifyToken']],function(){
    Route::match(['POST','OPTIONS'],'someDo','someController@someFunc');
})

4.客戶端可根據響應碼不一樣進行處理。完。

參考連接:
1.Github jtw-auth
2.Laravel 5 中使用 JWT(Json Web Token) 實現基於API的用戶認證 - laravel學院
3.JWT安全問題-翻譯 2015年

相關文章
相關標籤/搜索