【laravel】基於jwt實現用戶認證

安裝及基礎配置

使用 composer 安裝

# 建議使用1.0以上版本
composer require tymon/jwt-auth 1.*@rc

進行一些配置

有些文檔會說要添加 Tymon\JWTAuth\Providers\LaravelServiceProvider::class ,這隻在 Laravel 5.4 及如下版本是必要的,更新的 Laravel 版本無需添加。php

還有一些文檔說要添加 Tymon\JWTAuth\Providers\JWTAuthServiceProvider 這是好久之前的 JWT 版本的(大概0.5.3 之前的版本)。laravel

發佈配置文件

# 這條命令會在 config 下增長一個 jwt.php 的配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

生成加密密鑰

# 這條命令會在 .env 文件下生成一個加密密鑰,如:JWT_SECRET=foobar
php artisan jwt:secret

更新你的模型

若是你使用默認的 User 表來生成 token,你須要在該模型下增長一段代碼git

<?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 [];
    }
}

註冊兩個 Facade

這兩個 Facade 並非必須的,可是使用它們會給你的代碼編寫帶來一點便利。github

config/app.phpweb

'aliases' => [
        ...
        // 添加如下兩行
        'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
        'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],

若是你不使用這兩個 Facade,你能夠使用輔助函數 auth()json

auth() 是一個輔助函數,返回一個guard,暫時能夠當作 Auth Facade。api

能夠參考這篇文章——Laravel 輔助函數 auth 與 JWT 擴展詳解安全

// 若是你不用 Facade,你能夠這麼寫
auth('api')->refresh();
// 用 JWTAuth Facade
JWTAuth::parseToken()->refresh();

兩個 Facede 經常使用可以使用方法,能夠看文章後面的附錄。session

 修改 auth.php

config/auth.phpapp

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',      // 原來是 token 改爲jwt
        'provider' => 'users',
    ],
],

註冊一些路由

注意:在 Laravel 下,route/api.php 中的路由默認都有前綴 api

Route::group([

    'prefix' => 'auth'

], function ($router) {

    Route::post('login', 'AuthController@login');
    Route::post('logout', 'AuthController@logout');
    Route::post('refresh', 'AuthController@refresh');
    Route::post('me', 'AuthController@me');

});

建立 token 控制器

php artisan make:controller AuthController

AuthController

值得注意的是 Laravel 這要用 auth('api') ,至於爲何,我另外一篇關於 JWT 擴展詳解的文章裏有講

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;

class AuthController extends Controller
{
    /**
     * Create a new AuthController instance.
     * 要求附帶email和password(數據來源users表)
     * 
     * @return void
     */
    public function __construct()
    {
        // 這裏額外注意了:官方文檔樣例中只除外了『login』
        // 這樣的結果是,token 只能在有效期之內進行刷新,過時沒法刷新
        // 若是把 refresh 也放進去,token 即便過時但仍在刷新期之內也可刷新
        // 不過刷新一次做廢
        $this->middleware('auth:api', ['except' => ['login']]);
        // 另外關於上面的中間件,官方文檔寫的是『auth:api』
        // 可是我推薦用 『jwt.auth』,效果是同樣的,可是有更加豐富的報錯信息返回
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request(['email', 'password']);

        if (! $token = auth('api')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

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

    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        return response()->json(auth('api')->user());
    }

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

        return response()->json(['message' => 'Successfully logged out']);
    }

    /**
     * Refresh a token.
     * 刷新token,若是開啓黑名單,之前的token便會失效。
     * 值得注意的是用上面的getToken再獲取一次Token並不算作刷新,兩次得到的Token是並行的,即兩個均可用。
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth('api')->refresh());
    }

    /**
     * Get the token array structure.
     *
     * @param  string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ]);
    }
}

 使用 token

有兩種使用方法:

  • 加到 url 中:?token=你的token
  • 加到 header 中,建議用這種,由於在 https 狀況下更安全:Authorization:Bearer 你的token

添加中間件保護的就須要使用 token進行訪問

能夠使用的中間件有 auth、auth:api、jwt.auth、jwt.refresh、jwt.check、jwt.renew

關於這些中間件之間有什麼差異,能夠看另外一篇文章:Laravel 輔助函數 auth 與 JWT 擴展詳解

參考文檔

相關文章
相關標籤/搜索