Laravel 5.2 使用 JWT 进行多用户认证

Laravel 5.2 中本身自带了 auth 认证,也是支持多用户的,但是项目使用 Angular,所以后端只需要以接口的形式提供 json api 就可以了,这里就需要使用 JWT 来进行用户认证了,网上普遍的方式是使用 JWT-Auth 框架来进行 JWT 认证,但是发现 5.9 版本不支持多用户认证,1.0 之后才支持。但是由于 1.0 版本是 alpha 版本,所以 github 上并没有其相关文档,找了半天发现作者在某个 issue 里面提到了多用户的使用方法,遂在这里整理记录一下。

1 在 composer.json 文件的 require 中添加如下行来引入 JWT-Auth

"require": {
...
"tymon/jwt-auth": "^1.0@dev",
...
}

2 comfig/app.php 配置

providers 下添加

Tymon\JWTAuth\Providers\LaravelServiceProvider::class

aliases 下添加

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

3 terminal 下执行 php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider" 在 config 下生成 jwt.php 配置文件

4 terminal 下执行 php artisan jwt:secret 生成加密密钥

5 config/auth.php 设置相关参数

'guards' => [
...
'admin' => [
'driver' => 'jwt',
'provider' => 'admins',
],
],

'providers' => [
...
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],

6 route.php 中添加登录相关路由

Route::post('/auth/login', 'AuthController@login');

7 AuthController.php 中添加登录逻辑

<?php
namespace App\Http\Controllers\Admin;

use App\Models\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Validator;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Auth;

class AuthController extends Controller{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $guard = 'admin';
protected $username = 'username';

// 注册
public function register(Request $request){
$validator = $this->validator($request->all());
if ($validator->fails()) {
return $this->errorBadRequest($validator->messages(), 500);
}

$user = $this->create($request->all());

$credentials = [
'username' => $request['username'],
'password' => $request['password'],
];

$token = Auth::guard($this->getGuard())->attempt($credentials);
return $this->JSON(compact('token'));
}

// 登录
public function login(Request $request){
$this->validateLogin($request);

$throttles = $this->isUsingThrottlesLoginsTrait();

if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);

return $this->sendLockoutResponse($request);
}

$credentials = $this->getCredentials($request);

// 这里改用 JWT-Auth 进行认证
if ($token = Auth::guard($this->getGuard())->attempt($credentials)) {
return $this->handleUserWasAuthenticated($request, $throttles, $token);
}

if ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}

return $this->sendFailedLoginResponse($request);
}

// 刷新 token
public function refreshToken(){
$oldToken = JWTAuth::getToken();
$token = JWTAuth::refresh($oldToken);
return $this->JSON(compact('token'));
}

// 退出登录
public function logout(){
Auth::guard($this->getGuard())->logout();
return $this->JSON(array('status' => 'success'));
}


protected function validator(array $data){
return Validator::make($data, Admin::$rules);
}

protected function create(array $data){
return Admin::create([
'username' => $data['username'],
'password' => bcrypt($data['password']),
]);
}

protected function handleUserWasAuthenticated(Request $request, $throttles, $token){
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user(), $token);
}
return redirect()->intended($this->redirectPath());
}

protected function authenticated($request, $user, $token){
return self::JSON([
'user' => $user,
'token' => $token
]);
}

protected function sendFailedLoginResponse(Request $request){
return self::errorBadRequest($this->getFailedLoginMessage());
}

}

AuthController 中的 guard 属性可以指定在 auth.php 中声明的认证方式。

在其它需要认证才能访问的 controller 中可以使用中间件来判断

public function __construct(){
$this->middleware('auth:admin');
}

auth 中间件 Authenticate.php

public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}

参考

Feature: Laravel 5.2 Custom Authentication Guard and Driver
Add support & documentation for integrating with Lumen 5.2