【shiro】shiro整合JWT——3.执行流程

news2025/1/13 10:01:19

前言

shiro整合JWT系列,主要记录核心思路–如何在shiro+redis整合JWTToken。
上一篇中,主要讲如何在shiro框架中配置Jwt,以及token执行的流程。
该篇主要梳理整个代码的执行流程。
ps:本文主要以记录核心思路为主,以下都是个人理解,有问题请各位大佬指导一下

根据token的流程,请求主要分为2个情况:

  1. 登录获取token
  2. 携带token请求

1、登录获取token

在shiro+redis+jwt中,Controller层的登录接口不用执行subject.login(token)方法(没有用到Realm的doCredentialsMatch验证,可以参照【Shiro】SimpleAuthenticationInfo如何验证password),而是在Controller层手写了校验方法。

  • 逻辑如下:
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public xxx返回类 login(@RequestBody SysUser user) throws Exception{
	
	// 1、获取前端请求的 用户名和密码
	
	// 2、校验用户是否有效
		2.1 根据用户名查询数据库,得到用户数据库信息BDUser(用户名,加密密码,盐值...2.2 判断有效性(用户是否存在,是否注销,是否被删除)

	// 3、校验用户名或密码是否正确
		3.1 使用(前端传来的用户名,密码,DBUser.盐值)进行加密计算,得到加密密码
		3.2 判断是否正确,加密密码.equals(DBUser.getPassWord())

	// 4、生成token,并将token存入redis缓存中
	
	// 5、设置xxx返回类对象(主要把token返回去)
	
	}

从上面逻辑可以看出,这个登录接口主要就给前端返回了一个token,并将其存入redis中
这个登录接口,并没有真正进行登录操作subject.login(token),因此也没执行到Realm中的认证。

2、携带token请求

这里主要以流程介绍为主,通过简单的源码说明携带token请求的调用过程。通过【shiro】shiro整合JWT——1.需要创建的类 中的JwtFilter,我们可以看到,主要重写了preHandleisAccessAllowedexecuteLoginonAccessDenied这4个方法(该例子为简单实现)。

在JwtFilter中,这4个方法主要的执行顺序是
preHandle -> isAccessAllowed -> executeLogin -> onAccessDenied

2.1 preHandle

携带token的请求,先会被ShiroConfig中的filterChainDefinitionMap.put("/**", "jwt");给拦截,然后执行到我们定义的JwtFilter中;在JwtFilter中,会根据Filter中具体的doFilter方法实现(这里不细说,后续在细讲)。

/**
     * 对跨域提供支持
     * 过滤器链中拦截请求,判断是否为跨域请求
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        // 判断请求方式是否为跨域请求
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
            httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
            httpServletResponse.setHeader("Access-Control-Allow-Methods", httpServletRequest.getHeader("Access-Control-Request-Method"));
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            return false;
        }
        // 继续执行过滤器链
        return super.preHandle(request, response);
    }

preHandle方法在最后return了super.preHandle(request, response);,点进去查看,可以发现它重写PathMatchingFilter中的preHandle,然后再回调回了PathMatchingFilter中的preHandle。(看上去有点绕,看下图)
在这里插入图片描述

总结:感觉就是PathMatchingFilter类是主线流程,(重写的)preHandle方法B就是在preHandle方法A中加入我们自定义的内容,然后再继续执行preHandle方法A原有的内容。

顺着源码继续往下梳理流程,先看preHandle的代码,发现执行了isFilterChainContinued方法,里面又执行了onPreHandle方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 疑惑:这个重写的是哪个方法?
    回答:我们顺着JwtFilter的继承方法网上查找,如下图;可以发现,是由AccessControlFilter类重写的。在这里插入图片描述
    点进去AccessControlFilter类可以看到我们重写的方法isAccessAllowedonAccessDenied,中间的关系是具有 先后顺序的或。
    在这里插入图片描述

2.2 isAccessAllowed

	/**
     * 执行登录认证
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        try {
            executeLogin(request, response);
            return true;
        } catch (Exception e) {
            throw new AuthenticationException("Token失效请重新登录");
        }
    }

里面执行了executeLogin方法

2.3 executeLogin

	/**
     * 执行登录
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = httpServletRequest.getHeader("ACCESS_TOKEN");

        JwtToken jwtToken = new JwtToken(token);
        // 提交给realm进行登入,如果错误他会抛出异常并被捕获 
        // 这里真正实现shiro的登录,getSubject(request, response)直接SecurityUtils.getSubject()也一样
        getSubject(request, response).login(jwtToken);
        // 如果没有抛出异常则代表登入成功,返回true
        return true;
    }

对于getSubject(request, response).login(jwtToken);有疑惑的可以看下【shiro】subject.login(token)流程源码分析

PS:以防万一,遗忘却又没有看,这里根据总结图做下提示,执行getSubject(request, response).login(jwtToken)方法后,就会执行到Realm的认证方法。

2.4 onAccessDenied

根据源码,我们知道isAccessAllowed执行返回为True的话,就不会执行onAccessDenied(也就意味着登录成功,走向realm的两个方法);如果执行返回为False的话,就会执行onAccessDenied,用来处理登录失败的情况。

	/**
     * 如果没有登录,直接返回401未授权提示
     *
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // 这里是个坑,如果不设置的接受的访问源,那么前端都会报跨域错误,因为这里还没到corsConfig里面
        httpResponse.setHeader("Access-Control-Allow-Origin", ((HttpServletRequest) request).getHeader("Origin"));
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json; charset=utf-8");
		httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        try {
            // 返回到前端信息
            httpResponse.getWriter().write("未登录或登录失效,请重新登录!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/601723.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb14(ajax02判断账号是否存在JSON介绍AJAX+JSON字符串和对象之间的转换JSON实现自动补全)

目录 一.AJAX实现即时检查用户名是否存在 1.1 效果预览 1.2 代码实现 ①html代码 ②ajax请求 ③底层代码 2.JSON概述. 2.1何为JSON. 2.2为什么需要JSON. 2.3JSON格式介绍. 2.3.1JSON对象格式. 2.3.2JSON数组格式. 2.3.3JSON对象数组格式. 3.JSON字符串的解析. 3.1…

springboot启动过程原理分析

前言 现在绝大多数java项目都上了Springboot框架, 因此深入理解Springboot框架的运行原理,能帮助我们更好的在Springboot框架下进行业务开发,同时能学习框架中优秀的设计思想, 本文主要是通过对Springboot源码的分析, 来理解整个springboot项目的启动流程. 因为Springboot不同…

Spring:Spring框架_事务传播和隔离级别 ④

一、事务和四大特性 事务:指数据库的一个执行操作单元 事务的四个特性(ACID) 1.1 原子性 原子性(Atomicity):操作这些指令时,要么全部执行成功,要么全部不执行。只要…

JUC 学习笔记

JUC 学习笔记 本文为笔者对 JUC 的学习记录,主要参考了尚硅谷的 JUC 教程 文章目录 JUC 学习笔记1. JUC 概述什么是 JUC?线程和进程:进程的状态:wait 和 sleep:并发和并行:管程:用户线程和守护…

Python numpy - 数组的向量化运算

目录 一 函数numpy.where 二 数组统计方法 1 基础数组统计方法 2 布尔值数组的方法 三 排序 1 函数sort 2 函数np.unique 向量化:利用数组表达式来替代显式循环的方法 一 函数numpy.where 条件逻辑函数 where(condition, x, y) condition为条件,当满足条件…

有限状态机器测试(过渡游览法)

有限状态机器测试(过渡游览法) 测试相关概念—故障类型 行为由转换定义。 故障分为三种类型: 输出错误Output faults:错误的输出是由转换产生的。 状态转移错误State transfer faults:转移到错误的状态。 额外的状态Extra states&#xff08…

医院检验科检验系统(LIS)源码:临检、生化、免疫、微生物

一、检验科检验系统 (LIS)概述:对接HIS,医生工作站能够方便、及时的查阅患者检验报告。 二、检验科检验系统 (LIS)主要功能描述: 1.质控品管理: 医院设备质控(编码、设…

数据结构入门7-2(散列表)

注 本笔记参考:《数据结构(C语言版)(第2版)》 散列表的基本概念 像基于线性表、数表的查找方式,往往都是以关键字的比较为基础的。这种比较方式在遇到结点数量很多的情况时就会暴露其的弊端:需要…

vue3-实战-03-管理后台路由分析搭建和登录模块开发

1-路由的搭建 先分析模块,搭建一些基础的路由信息,我们分析需要登录页面路由,登录成功后展示数据路由,404页面路由,以及我们输入错误的路径的我们需要重定向到404路由。配置好相关路由之后,我们需要在入口文…

基于 ESP32-H2 构建高性价比的安全物联网设备

如今,人们对网联设备安全性的认识和关注不断增加。在欧盟《网络弹性法案》也即将生效的,为网联设备增加硬件层面的安全功能非常重要。 乐鑫 ESP32-H2 致力于为所有开发者提供高性价比的安全解决方案,这款芯片经过专门设计以集成多种安全功能…

【java】java访问https并验证账号密码

java访问https,获取页面或者数据时,需要证书和账号密码的验证。 一 获取CRT证书 获取网站的证书,拿到证书后可能是crt格式,可以使用下面的命令转为p12格式 openssl pkcs12 -export -in Mycert.crt -inkey Mykey.key -out Mycer…

0基础学习VR全景平台篇第35篇:场景功能-细节

本期为大家带来蛙色VR平台,场景管理—细节功能操作。 功能位置示意 一、本功能将用在哪里? 细节功能,用于展示VR漫游作、大像素、高清矩阵作品中细微不容易发现,但却又比较有亮点或者能起到关键作用的画面。 通过在全景图中添加…

javaWeb ssh课程资源网站myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh课程资源网站系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用 B/S模式开发。开发环境为TOMCAT7.…

字节的测试面试题,你觉得很难吗?不是有手就行....

年前的时候,我的一个粉丝跟我说,他在面试美团的自动化测试岗的时候,不幸挂掉了。 越想越可惜,回想面试经过,好好总结了几个点,发现面试没过的主要原因是在几个关键的问题没有给到面试官想要的答案 字节的…

6-HEX, SE,引物荧光标记试剂,胺反应性琥珀酰亚胺酯,广泛用于nucleic acid测序和相关研究

6-HEX, SE | 6-HEX,SE [6-羧基-2,4,4,5,7,7-六氯荧光素,琥珀酰亚胺酯] |CAS:N/A | 纯度:95% (文章资料汇总来源于:陕西新研博美生物科技有限公司小编MISSwu)​ 结构…

Android Cannot resolve symbol 找不到资源解决方案

一、介绍 在android开发中,我们经常会发现依赖了系统提供的库,但是无法引用,或者找不到, Cannot resolve symbol style/Theme.AppCompat.NoActionBar ,报红。这些最经典的无法加载。 出现这个原因并不是你项目的原因&…

手把手教你如何正确永久使用Microsoft Office365?

office2019和office 365有什么区别的呢?为什么越来越多的人更加钟爱office365。简单来说office 2019的零售版本属于一次售出永久使用,价格上比较贵,而且功能上也不会再有更新。而office 365是一种基于云的订阅服务,我们花钱买的是…

Datax同步MySQL到ES

Datax同步MySQL到ES 1、在MySQL中建表2、在ES建立索引3、构建从MySQL到ES的Datax的Json任务4、运行mysql2es.json脚本以下是工作中做过的ETL,如有需要,可以私信沟通交流,互相学习,一起进步 1、在MySQL中建表 建表语句 CREATE TABL…

如何在Flutter 中启用空安全

目录 Step 1: 开启空安全设置 Step 2:检查可升级的三方库 Step 3:升级三方库 Step 4:代码适配支持空安全 Step 1: 开启空安全设置 Flutter 2默认启用了空安全,所以通过Flutter 2创建的项目是已经开启了空安全的检查的,不知道自己是什么版本的可以通…

【MCS-51单片机汇编语言】期末复习总结①——常见指令汇总(题型一)

文章目录 七大寻址方式重要指令转移堆栈加减乘除位操作跳转条件转移子程序常考题型 七大寻址方式 立即寻址:通过一个立即数来指定存储单元的地址,例如#41H;寄存器寻址:Rn(n0~7),A,B&#xff0c…