欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

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

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

来自 http://honglu.me/2016/08/20/Laravel%E4%BD%BF%E7%94%A8JWT%E5%A4%9A%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81/
普通分类: