1. 程式人生 > >Laravel5使用 Jwt-Auth 實現 API 使用者認證

Laravel5使用 Jwt-Auth 實現 API 使用者認證

jwt-auth 最新版本是 1.0.0 rc.1 版本,已經支援了 Laravel 5.5。如果你使用的是 Laravel 5.5 版本,可以使用如下命令安裝。

如果你是 Laravel 5.5 以下版本,也推薦使用最新版本,RC.1 前的版本都存在多使用者token認證的安全問題。

 composer require tymon/jwt-auth 1.0.0-rc.1

新增服務提供商

將下面這行新增至 config/app.php 檔案 providers 陣列中:

Tymon\JWTAuth\Providers\LaravelServiceProvider::class,

將下面這行新增至 config/app.php

檔案 aliases陣列中:

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

在你的 shell 中執行如下命令釋出 配置檔案:

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

此命令會在 config 目錄下生成一個 jwt.php 配置檔案,你可以在此進行自定義配置。

生成金鑰

php artisan jwt:secret

此命令會在你的 .env 檔案中新增一行 JWT_SECRET=secret

配置 Auth guard

在 config/auth.php 檔案中,你需要將 guards/driver 更新為 jwt

'defaults' => [
    'guard' => 'api',         // 修改為api
    'passwords' => 'users',
],

'guards' => [
    'api' => [
        'driver' => 'jwt',     // JWTGuard 實現,原始碼中為 token,我這改成 jwt 了
        'provider' => 'users',
    ],
],

'providers' => [
     'users' => [
          'driver' => 'eloquent',
          'model' => App\Models\User::class, // 根據你model的位置更改
     ],
],

更改 Model

如果需要使用 jwt-auth 作為使用者認證,我們需要對我們的 User 模型進行一點小小的改變,變更後的 User 模型如下:

<?php

namespace App\Models;

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

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;
    protected $table = 'users';
    protected $fillable = ['name', 'password', 'mobile'];
    #定義是否預設維護時間,預設是true.改為false,則以下時間相關設定無效
    public $timestamps = true;
    protected $hidden = [
        'password',
    ];
    /**
     * 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 [];
    }

}

使用者提供賬號密碼前來登入。如果登入成功,那麼我會給前端頒發一個 access _token 

執行如下命令以新建一箇中間件:

php artisan make:middleware ApiAuth

中介軟體程式碼 ApiAuth.php 如下:

<?php
namespace App\Http\Middleware;


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

class ApiAuth
{
    public function handle($request, Closure $next)
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {  //獲取到使用者資料,並賦值給$user
                return response()->json([
                    'errcode' => 1004,
                    'errmsg' => 'user not found'

                ], 404);
            }
        return $next($request);

    } catch (TokenExpiredException $e) {

            return response()->json([
                'errcode' => 1003,
                'errmsg' => 'token 過期' , //token已過期
            ]);

        } catch (TokenInvalidException $e) {

            return response()->json([
                'errcode' => 1002,
                'errmsg' => 'token 無效',  //token無效
            ]);

        } catch (JWTException $e) {

            return response()->json([
                'errcode' => 1001,
                'errmsg' => '缺少token' , //token為空
            ]);

        }
    }

}

在app\Http\Kernel.php下新增如下程式碼

 protected $routeMiddleware = [
        'api.auth' => \App\Http\Middleware\ApiAuth::class,
 ];

現在,我們可以在 routes/api.php 路由檔案中路由來測試一下

Route::post('login', '[email protected]');
Route::post('register', '[email protected]');

控制器程式碼如下: 

use JWTAuth;

public function login(Request $request)
{
   // 驗證規則,由於業務需求,這裡我更改了一下登入的使用者名稱,使用手機號碼登入
    $rules = [
         'mobile'   => ['required'],
         'password' => 'required|string|min:6|max:20',
    ];

    // 驗證引數,如果驗證失敗,則會丟擲 ValidationException 的異常
    $params = $this->validate($request, $rules);

    // 使用 Auth 登入使用者,如果登入成功,則返回 201 的 code 和 token,如果登入失敗則返回
    $token = JWTAuth::attempt($params);
    if ($token) {
        return $this->responseData(['access_token' => $token]);
    } else {
        $this->responseError('賬號或密碼錯誤');
    }

}

public function register(RegisterRequest $request)
{
    $mobile = $request->input('mobile');
    $password = $request->input('password');
    // 註冊使用者
    $user = User::create([
         'mobile' => $mobile,
         'password' => bcrypt($password),
         'nickname' => encryptedPhoneNumber($mobile)
    ]);
    // 獲取token
    $token = JWTAuth::fromUser($user);
     if (!$token) {
         return $this->responseError('註冊失敗,請重試');
     }

     return $this->responseData([
         'access_token' => $token,
         'user' => $user
     ]);
}

測試截圖如下:

 

純原創,希望可以對大家有幫助,文章會不斷更新,如有疑問或新坑,歡迎評論