laravel 安裝jwt-auth及驗證php
一、使用composer安裝jwt,cmd到項目文件夾中;node
composer require tymon/jwt-auth 1.0.*(這裏版本號根據本身的須要寫)laravel
安裝jwt ,參考官方文檔https://jwt-auth.readthedocs.io/en/docs/laravel-installation/web
二、若是laravel版本低於5.4json
打開根目錄下的config/app.phpapi
在'providers'數組裏加上Tymon\JWTAuth\Providers\LaravelServiceProvider::class,數組
'providers' => [ ... Tymon\JWTAuth\Providers\LaravelServiceProvider::class,]安全
三、在 config 下增長一個 jwt.php 的配置文件session
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"架構
四、在 .env 文件下生成一個加密密鑰,如:JWT_SECRET=foobar
php artisan jwt:secret
五、在user模型中寫入下列代碼
<?php namespace App\Model; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { // Rest omitted for brevity protected $table="user"; public $timestamps = false; public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
六、註冊兩個 Facade
config/app.php
'aliases' => [ ... // 添加如下兩行 'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth', 'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory', ],
七、修改 auth.php
config/auth.php
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', // 原來是 token 改爲jwt 'provider' => 'users', ], ],
八、註冊路由
Route::group([ 'prefix' => 'auth' ], function ($router) { $router->post('login', 'AuthController@login'); $router->post('logout', 'AuthController@logout'); });
九、建立token控制器
php artisan make:controller AuthController
代碼以下:
<?php namespace App\Http\Controllers; use App\Model\User; use Illuminate\Http\Request; use Tymon\JWTAuth\Facades\JWTAuth; class AuthController extends Controller { /** * Create a new AuthController instance. * * @return void */ public function __construct() { $this->middleware('auth:api', ['except' => ['login']]); } /** * 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(JWTAuth::parseToken()->touser()); } /** * Log the user out (Invalidate the token). * * @return \Illuminate\Http\JsonResponse */ public function logout() { JWTAuth::parseToken()->invalidate(); return response()->json(['message' => 'Successfully logged out']); } /** * Refresh a token. * * @return \Illuminate\Http\JsonResponse */ public function refresh() { return $this->respondWithToken(JWTAuth::parseToken()->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' => JWTAuth::factory()->getTTL() * 60 ]); } }
注意:attempt 一直返回false,是由於password被加密了,使用bcrypt或者password_hash加密後就能夠了
十、驗證token獲取用戶信息
有兩種使用方法:
加到 url 中:?token=你的token
加到 header 中,建議用這種,由於在 https 狀況下更安全:Authorization:Bearer 你的token
十一、首先使用artisan命令生成一箇中間件,我這裏命名爲RefreshToken.php,建立成功後,須要繼承一下JWT的BaseMiddleware
代碼以下:
<?php namespace App\Http\Middleware; use Auth; use Closure; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Http\Middleware\BaseMiddleware; use Tymon\JWTAuth\Exceptions\TokenExpiredException; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; // 注意,咱們要繼承的是 jwt 的 BaseMiddleware class RefreshToken extends BaseMiddleware { /** * Handle an incoming request. * * @ param \Illuminate\Http\Request $request * @ param \Closure $next * * @ throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException * * @ return mixed */ public function handle($request, Closure $next) { // 檢查這次請求中是否帶有 token,若是沒有則拋出異常。 $this->checkForToken($request); // 使用 try 包裹,以捕捉 token 過時所拋出的 TokenExpiredException 異常 try { // 檢測用戶的登陸狀態,若是正常則經過 if ($this->auth->parseToken()->authenticate()) { return $next($request); } throw new UnauthorizedHttpException('jwt-auth', '未登陸'); } catch (TokenExpiredException $exception) { // 此處捕獲到了 token 過時所拋出的 TokenExpiredException 異常,咱們在這裏須要作的是刷新該用戶的 token 並將它添加到響應頭中 try { // 刷新用戶的 token $token = $this->auth->refresh(); // 使用一次性登陸以保證這次請求的成功 Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']); } catch (JWTException $exception) { // 若是捕獲到此異常,即表明 refresh 也過時了,用戶沒法刷新令牌,須要從新登陸。 throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage()); } } // 在響應頭中返回新的 token return $this->setAuthenticationHeader($next($request), $token); } }
這裏主要須要說的就是在token進行刷新後,不但須要將token放在返回頭中,最好也將請求頭中的token進行置換,由於刷新事後,請求頭中的token就已經失效了,若是接口內的業務邏輯使用到了請求頭中的token,那麼就會產生問題。
這裏使用
$request->headers->set('Authorization','Bearer '.$token);
將token在請求頭中刷新。
建立而且寫完中間件後,只要將中間件註冊,而且在App\Exceptions\Handler.php內加上一些異常處理就ok了。
十二、kernel.php文件中
$routeMiddleware 添加中間件配置
'RefreshToken' => \App\Http\Middleware\RefreshToken::class,
1三、添加路由
Route::group(['prefix' => 'user'],function($router) { $router->get('userInfo','UserController@userInfo')->middleware('RefreshToken'); });
在控制器中經過 JWTAuth::user();就能夠獲取用戶信息
更多PHP內容請訪問: