Laravel使用Dingo API+JWT实现认证机制 无痛刷新Token_dingoapi刷新token-程序员宅基地

技术标签: laravel  jwt  php  api  

一、安装Dingo APIJWT

1. 执行composer命令

composer require dingo/api
composer require tymon/jwt-auth

2. 修改config/app.php

'providers' => [
	Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]
'aliases' => [
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
]

3. 执行命令发布配置

php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

4. 添加.env配置

API_STANDARDS_TREE=vnd # 表示公开发布的项目
API_SUBTYPE=myapp # 项目缩写
API_PREFIX=api # 前缀,不需要可以填写'/',和API_DOMAIN二选一
API_VERSION=v1 # 版本号
API_NAME=myapp # 名字(使用API Blueprint命令生成文档是才会用到)
API_CONDITIONAL_REQUEST=false # 条件请求默认为开启状态,这有利于客户端的缓存机制在可能的情况下缓存API请求
API_STRICT=false # 严格模式将要求客户端发送Accept标头,代替配置文件中指定的版本。这意味着无法通过浏览器访问API。
API_DEFAULT_FORMAT=json # 响应格式,默认JSON格式
API_DEBUG=false # 调试模式

JWT_SECRET=VgjyyixSPOGS9DqOuwNDmGvuqiq4c5MKBfK16uCb11ihbYadG9N8KjqMoBBDkk1q #密钥 通过php artisan jwt:secret命令生成
JWT_TTL=60 #token有效期,默认60分钟,单位分钟,ttl失效,refresh_ttl有效时可以刷新获取新的token
JWT_REFRESH_TTL=20160 #token允许刷新时间,默认20160分钟(2周),单位分钟,refresh_ttl失效后,需要重新登陆。
JWT_BLACKLIST_ENABLED=true #黑名单,默认true,建议开启,不开启无法让token失效。
JWT_BLACKLIST_GRACE_PERIOD=10 #宽限时间,单位秒,ttl失效,refresh_ttl有效时宽限时间内的请求会被允许;并发请求时,token被刷新后,防止后续请求失败。

5. 修改config/auth.php

'defaults' => [
    'guard' => 'api',
    'passwords' => 'users',
],
'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],
'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\PreUsersModel::class,
        ],
    ],

二、修改Model

<?php

namespace App\Models;

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

class PreUsersModel extends Authenticatable implements JWTSubject
{
    
    protected $table = 'pre_users';
    protected $primaryKey = 'id';

    const STATUS_OFF = 0;
    const STATUS_ON = 1;

    public static $statusMap = [
        self::STATUS_OFF => '禁用',
        self::STATUS_ON => '启用',
    ];

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

三、添加路由

<?php

$api = app('Dingo\Api\Routing\Router');

$api->version('v1', ['namespace' => 'App\Api\V1\Controllers'], function ($api) {
    

    /**
     * auth
     */
    $api->post('v1/auth/login', 'AuthController@login');

    /**
     * token权限访问
     */
    $api->group(['middleware' => 'refresh.token'], function ($api) {
    

        /**
         * auth
         */
        $api->delete('v1/auth/logout', 'AuthController@logout');
        $api->put('v1/auth/refresh', 'AuthController@refresh');

        /**
         * user
         */
        $api->get('v1/user/info', 'UserController@info');
    });
});

四、添加控制器

1. app/Api/V1/Controllers/AuthController.php

<?php

namespace App\Api\V1\Controllers;

use App\Models\PreUsersModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class AuthController extends BaseController
{
    
    /**
     * 登陆
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
    
        $validator = Validator::make($request->all(), [
            'mobile' => 'required|string|min:11',
            'password' => 'required|string|min:5',
        ]);

        if ($validator->fails()) return response()->json(['message' => '参数错误'], 422);

        $user = PreUsersModel::where('mobile', $request->input('mobile'))->first();


        if (empty($user) || !Hash::check($request->input('password'), $user->password)) {
    
            return response()->json(['message' => '用户名或密码错误'], 500);
        }

        if ($user->status == PreUsersModel::STATUS_OFF) {
    
            return response()->json(['message' => '帐号已禁用'], 500);
        }

        if ($token = $this->guard()->fromUser($user)) {
    
            return $this->respondWithToken($token, $user);
        }

        return response()->json(['message' => '登陆失败'], 500);
    }

    /**
     * 登出
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
    
        $this->guard()->logout();

        return response()->json(['message' => '登出成功']);
    }

    /**
     * 刷新token
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh(Request $request)
    {
    
        $user = $this->guard()->user();

        if ($user->status == PreUsersModel::STATUS_OFF) {
    
            return response()->json(['message' => '帐号已禁用'], 500);
        }

        $token = $this->guard()->refresh();

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

    /**
     * 带token返回
     * @param $token
     * @param $user
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token, $user)
    {
    
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => $this->guard()->factory()->getTTL() * 60,
            'user' => $user,
        ]);
    }

    /**
     * @return mixed
     */
    protected function guard()
    {
    
        return Auth::guard('api');
    }
}

2. app/Api/V1/Controllers/UserController.php

<?php

namespace App\Api\V1\Controllers;

class UserController extends BaseController
{
    

    /**
     * @return \Illuminate\Http\JsonResponse
     */
    public function info()
    {
    
        $user = auth()->user();

        return response()->json($user);
    }
}

五、添加中间件

1. 创建中间件

php artisan make:middleware RefreshToken

2. 修改app/Http/Kernel.php

    protected $routeMiddleware = [
        'refresh.token' => RefreshToken::class, //增加
    ];

3. 修改app/Http/Middleware/RefreshToken.php

<?php

namespace App\Http\Middleware;

use App\Models\PreUsersModel;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

// 继承jwt的BaseMiddleware
class RefreshToken extends BaseMiddleware
{
    
    /**
     * @param Request $request
     * @param Closure $next
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|mixed
     * @throws JWTException
     */
    public function handle(Request $request, Closure $next)
    {
    
        // 检查请求是否携带token
        $this->checkForToken($request);

        try {
    
            // 检测用户的登录状态
            if (!$this->auth->parseToken()->authenticate()) {
    
                response()->json(['message' => '未登录'], 401);
            }

            $user = $this->auth->user();
            if ($user->status == PreUsersModel::STATUS_OFF) {
    
                return response()->json(['message' => '帐号已禁用'], 500);
            }

            return $next($request);

        } catch (TokenExpiredException $exception) {
    
            // 如果捕获到此异常,即代表ttl过期了,刷新令牌,在response的头部返回token。
            try {
    
                $user_id = $this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub'];
                // 刷新token
                $token = $this->auth->refresh();
                // 使用一次性登录以保证此次请求的成功
                Auth::guard('api')->onceUsingId($user_id);
                // 在响应头中返回新的token
                return $this->setAuthenticationHeader($next($request), $token);
            } catch (JWTException $exception) {
    
                // 如果捕获到此异常,即代表refresh_ttl也过期了,用户无法刷新令牌,需要重新登录。
                return response()->json(['message' => '登陆状态已过期,请重新登陆'], 401);
            }
        }
    }
}

五、测试

推荐postman,下面说一下流程,就不放实测的截图了

  1. 修改JWT_TTL=1,JWT_REFRESH_TTL=2,JWT_BLACKLIST_GRACE_PERIOD=10
  2. 请求登陆接口获取token
  3. 添加Authorization:Bearer token头部,请求用户信息接口
  4. 1分钟后,token过期,宽限时间内会允许请求用户信息接口,并且response会带着Authorization:Bearer token头部返回,获取新token
  5. 使用新token请求用户信息接口成功
  6. 2分钟后,token过期,刷新时间也过期,提示重新登陆,response也没有Authorization头部返回
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Hannnnnnnnnnnnn/article/details/110847608

智能推荐

React学习记录-程序员宅基地

文章浏览阅读936次,点赞22次,收藏26次。React核心基础

Linux查磁盘大小命令,linux系统查看磁盘空间的命令是什么-程序员宅基地

文章浏览阅读2k次。linux系统查看磁盘空间的命令是【df -hl】,该命令可以查看磁盘剩余空间大小。如果要查看每个根路径的分区大小,可以使用【df -h】命令。df命令以磁盘分区为单位查看文件系统。本文操作环境:red hat enterprise linux 6.1系统、thinkpad t480电脑。(学习视频分享:linux视频教程)Linux 查看磁盘空间可以使用 df 和 du 命令。df命令df 以磁..._df -hl

Office & delphi_range[char(96 + acolumn) + inttostr(65536)].end[xl-程序员宅基地

文章浏览阅读923次。uses ComObj;var ExcelApp: OleVariant;implementationprocedure TForm1.Button1Click(Sender: TObject);const // SheetType xlChart = -4109; xlWorksheet = -4167; // WBATemplate xlWBATWorksheet = -4167_range[char(96 + acolumn) + inttostr(65536)].end[xlup]

若依 quartz 定时任务中 service mapper无法注入解决办法_ruoyi-quartz无法引入ruoyi-admin的service-程序员宅基地

文章浏览阅读2.3k次。上图为任务代码,在任务具体执行的方法中使用,一定要写在方法内使用SpringContextUtil.getBean()方法实例化Spring service类下边是ruoyi-quartz模块中util/SpringContextUtil.java(已改写)import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.s..._ruoyi-quartz无法引入ruoyi-admin的service

CentOS7配置yum源-程序员宅基地

文章浏览阅读2w次,点赞10次,收藏77次。yum,全称“Yellow dog Updater, Modified”,是一个专门为了解决包的依赖关系而存在的软件包管理器。可以这么说,yum 是改进型的 RPM 软件管理器,它很好的解决了 RPM 所面临的软件包依赖问题。yum 在服务器端存有所有的 RPM 包,并将各个包之间的依赖关系记录在文件中,当管理员使用 yum 安装 RPM 包时,yum 会先从服务器端下载包的依赖性文件,通过分析此文件从服务器端一次性下载所有相关的 RPM 包并进行安装。_centos7配置yum源

智能科学毕设分享(算法) 基于深度学习的抽烟行为检测算法实现(源码分享)-程序员宅基地

文章浏览阅读828次,点赞21次,收藏8次。今天学长向大家分享一个毕业设计项目毕业设计 基于深度学习的抽烟行为检测算法实现(源码分享)毕业设计 深度学习的抽烟行为检测算法实现通过目前应用比较广泛的 Web 开发平台,将模型训练完成的算法模型部署,部署于 Web 平台。并且利用目前流行的前后端技术在该平台进行整合实现运营车辆驾驶员吸烟行为检测系统,方便用户使用。本系统是一种运营车辆驾驶员吸烟行为检测系统,为了降低误检率,对驾驶员视频中的吸烟烟雾和香烟目标分别进行检测,若同时检测到则判定该驾驶员存在吸烟行为。进行流程化处理,以满足用户的需要。

随便推点

STM32单片机示例:多个定时器同步触发启动_stm32 定时器同步-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏14次。多个定时器同步触发启动是一种比较实用的功能,这里将对此做个示例说明。_stm32 定时器同步

android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...-程序员宅基地

文章浏览阅读348次。出处 : http://www.cnblogs.com/mythou/p/3187881.html本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务。客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题。没办法,只能看看是怎么回事。今天分析一下Launcher启动APP的过程。从用户点击到程序启动的流程,下面针对WorkSpa..._回调bubbletextview

Ubuntu 12 最快的两个源 个人感觉 163与cn99最快 ubuntu安装源下包过慢_un.12.cc-程序员宅基地

文章浏览阅读6.2k次。Ubuntu 12 最快的两个源 个人感觉 163与cn99最快 ubuntu下包过慢 1、首先备份Ubuntu 12.04源列表 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup (备份下当前的源列表,有备无患嘛) 2、修改更新源 sudo gedit /etc/apt/sources.list (打开Ubuntu 12_un.12.cc

vue动态路由(权限设置)_vue动态路由权限-程序员宅基地

文章浏览阅读5.8k次,点赞6次,收藏86次。1.思路(1)动态添加路由肯定用的是addRouter,在哪用?(2)vuex当中获取到菜单,怎样展示到界面2.不管其他先试一下addRouter找到router/index.js文件,内容如下,这是我自己先配置的登录路由现在先不管请求到的菜单是什么样,先写一个固定的菜单通过addRouter添加添加以前注意:addRoutes()添加的是数组在export defult router的上一行图中17行写下以下代码var addRoute=[ { path:"/", name:"_vue动态路由权限

JSTL 之变量赋值标签-程序员宅基地

文章浏览阅读8.9k次。 关键词: JSTL 之变量赋值标签 /* * Author Yachun Miao * Created 11-Dec-06 */关于JSP核心库的set标签赋值变量,有两种方式: 1.日期" />2. 有种需求要把ApplicationResources_zh_CN.prope

VGA带音频转HDMI转换芯片|VGA转HDMI 转换器方案|VGA转HDMI1.4转换器芯片介绍_vga转hdmi带音频转换器,转接头拆解-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏2次。1.1ZY5621概述ZY5621是VGA音频到HDMI转换器芯片,它符合HDMI1.4 DV1.0规范。ZY5621也是一款先进的高速转换器,集成了MCU和VGA EDID芯片。它还包含VGA输入指示和仅音频到HDMI功能。进一步降低系统制造成本,简化系统板上的布线。ZY5621方案设计简单,且可以完美还原输入端口的信号,此方案设计广泛应用于投影仪、教育多媒体、视频会议、视频展台、工业级主板显示、手持便携设备、转换盒、转换线材等产品设计上面。1.2 ZY5621 特性内置MCU嵌入式VGA_vga转hdmi带音频转换器,转接头拆解

推荐文章

热门文章

相关标签