nftkif链之家/网站免费seo
1. 应用场景
前后端分离项目保持登录状态。
问题:ajax请求如何跨域,将无法携带jsessionid,这样会导致服务器端的session不可用。如何解决?
后端:
登录接口在验证过用户密码后,将用户的身份信息转换成一个特殊格式的字符串(token),放入响应体(或响应头)。
前端:
浏览器收到登录成功响应后,保存该token在本地,当下次发送请求时,取出该token并携带在请求头(或请求体中)。
后端:
使用filter或者拦截器校验请求中的token是否有效,如果有效就代表用户已登录,放行。
2. 对于token的需求
(1) 可以自定义信息(用户身份、权限信息)
(2) 需要使得服务器端可以进行有效性校验(即token只能由服务器端颁发,不能由其他第三方伪造)
(3) 需要能设置有效期
3. JWT的数据结构
https://jwt.io/ 官网地址
(1)HEADER //头
(2)PAYLOAD //体
(3)SIGNATURE //签名
4. 生成JWT
HMACSHA256(
base64UrlEncode(header) + "." +base64UrlEncode(payload),
your-256-bit-secret
)
(1)计算header的base64编码
(2)计算payload的base64编码
(3)计算签名
5. 校验token是否合法
原理:重新计算token的sign,与token中的sign进行比对,一致则合法。
6. 校验token有效期
原理,在jwt的payload中加入过期日期,然后在校验token时检查是否过期
这是一个测试类需要导入Hutool工具类
package com.qf.fmall.jwt;import cn.hutool.jwt.JWT;import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;public class TestJwt {public static final String secretkey="qfsyjava2302";public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {String token1 = createToken();//验证token的合法性
// String token="eyJoZWFkZXIwMSI6InRlc3QxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsdWZmeSIsImlhdCI6MTY5MzIwNjc2NiwicGhvbmUiOiIxMzg5OTk5ODg4OCIsInNleCI6MSwiYWdlIjoxOX0.UY3v3twt30GAN6iCOlTTZwA0YpwMBFDg3JyWgxp1_7U";Thread.sleep(3000);//使用hutool工具类校验Jwtboolean validate = JWT.of(token1)//把token字符串传入,用来构建jwt对象.setKey(secretkey.getBytes("utf-8"))//传入计算签名要使用的密钥
// .verify() 只验证token值,不验证时间.validate(3l);//校验jwt是否合法,本质上就是重算签名,并且比较签名是否一致。//这里的leeway是秒,就是在原本的设定的失效时间,容许容忍几秒System.out.println(validate);}public static String createToken() throws UnsupportedEncodingException {//利用hutool工具类生成JwtHashMap<String, Object> payloadMap = new HashMap<>();payloadMap.put("age",19);payloadMap.put("sex",1);payloadMap.put("phone","13899998888");HashMap<String, Object> headMap = new HashMap<>();headMap.put("header01","test123");String token = JWT.create().addHeaders(headMap) //放入自定义Jwt 头.setSubject("luffy")//在 jwt 的payload中放入 sub(代表用户身份信息).setExpiresAt(new Date(System.currentTimeMillis()+1000*3))// 在jwt的payload中放入 jwt 失效时间.setIssuedAt(new Date()) //在 jwt 的payload 中 放入 jwt的签发时间.addPayloads(payloadMap) // 在jwt 的payload 中放入其他自定义内容.setKey(secretkey.getBytes("utf-8")) //放入计算jwt 需要的密钥字符串.sign();System.out.println(token);return token;
}}
7. 开启shiro登录校验
1.用拦截器的方式实现
实现拦截器接口
package com.qf.fmall.interceptor;import cn.hutool.jwt.JWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//0.判断如果是浏览器发送的Option 请求,直接放行String method = request.getMethod();if (method.equals("OPTIONS")){return true;}//1.获取 请求头中的 tokenString token= request.getHeader("token");//校验jwttokenif (token==null){log.info("没带token,拒绝访问");return false;}boolean validate = JWT.of(token).setKey("qfsyjava2302".getBytes("utf-8")).validate(0);return validate;}
}
注册拦截器
package com.qf.fmall.config;import com.qf.fmall.interceptor.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class IntercepterConfig implements WebMvcConfigurer {@AutowiredJwtInterceptor jwtInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(jwtInterceptor).addPathPatterns("/index/indeximg");}
}
2.整合shiro过滤器
1.前端登录方法
@GetMapping("/login")@CrossOriginpublic ResultVo login(@RequestParam("username") String username,@RequestParam("password") String password) throws JsonProcessingException {Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token =new UsernamePasswordToken(username,password);try {subject.login(token);Users principal = (Users) subject.getPrincipal();//当用户登录成功之后,创建jwt//把principal---> jsonObjectMapper mapper = new ObjectMapper();//获取springboot内置的json转换对象String userjson = mapper.writeValueAsString(principal);String jwt = JWT.create().setSubject(userjson).setExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 30)).setIssuedAt(new Date()).setKey("qfsyjava2302".getBytes()).sign();return ResultVo.vo(10000,jwt,principal);} catch (AuthenticationException e) {e.printStackTrace();return ResultVo.vo(112300,"failed",null);}}
2.后端验证过滤器
package com.qf.fmall.filter;import cn.hutool.jwt.JWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.stereotype.Component;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;@Component("jwt")
@Slf4j
public class JwtFilter extends AccessControlFilter {/*** 用于验证访问受保护的方法* @param servletRequest* @param servletResponse* @param o* @return* @throws Exception*/@Overrideprotected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {HttpServletRequest request = (HttpServletRequest) servletRequest;//0.判断如果是浏览器发送的Option 请求,直接放行String method = request.getMethod();if (method.equals("OPTIONS")){return true;}//1.获取 请求头中的 tokenString token= request.getHeader("token");//校验jwttokenif (token==null){log.info("没带token,拒绝访问");return false;}boolean validate = JWT.of(token).setKey("qfsyjava2302".getBytes("utf-8")).validate(0);return validate;}/*** onAccessDenied 方法是Shiro框架中的一个回调方法,当主体(用户)被拒绝访问特定资源时会被调用。该方法不返回布尔值。* 当主体尝试访问受保护的资源但权限不足或未认证时,Shiro会触发 onAccessDenied 方法。通常,它用于处理被拒绝访问的情况,例如将用户重定向到错误页面或返回错误消息。* 因此,说 onAccessDenied 方法返回 true 是没有意义的。该方法的目的是处理访问被拒绝的情况,而不是返回布尔值。* @param servletRequest* @param servletResponse* @return* @throws Exception*/@Overrideprotected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {return false;}
}
3.让请求走shiro过滤器
在ShiroConfig类下写
//配置Shiro过滤器链@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();chainDefinition.addPathDefinition("/user/login**","anon");chainDefinition.addPathDefinition("/user/regist**","anon");chainDefinition.addPathDefinition("/error","anon");//让/index/indeximg 由自定义的shiro filter 进行处理, "jwt" 这个值是IOC容器中filter的名字chainDefinition.addPathDefinition("/index/indeximg","jwt");
// chainDefinition.addPathDefinition("/**","authc");return chainDefinition;}
但是shiro不仅会在shiro过滤器链下注册此过滤器,还会在springmvc过滤器链上注册
所以我们,还要让springmvc上的过滤器链上的此过滤器失效
4.让全局过滤器链上的JwtFilter失效
package com.qf.fmall.config;import com.qf.fmall.filter.JwtFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 注意,为了不让 自定义filter也被中注册到全局FitlterChain中,* 需要添加如下配置类*/
@Configuration
public class FilterConfig {@AutowiredJwtFilter jwtFilter;@Beanpublic FilterRegistrationBean<JwtFilter> jwtFilterFilterRegistrationBean(){FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();//要注册的filter的对象registrationBean.setFilter(jwtFilter);//让当前filter不用注册到,全局过滤器链上registrationBean.setEnabled(false);return registrationBean;}}
相关文章:

Springboot整合JWT
1. 应用场景 前后端分离项目保持登录状态。 问题:ajax请求如何跨域,将无法携带jsessionid,这样会导致服务器端的session不可用。如何解决? 后端: 登录接口在验证过用户密码后,将用户的身份信息转换成…...

如何使用Python和正则表达式处理XML表单数据
在日常的Web开发中,处理表单数据是一个常见的任务。而XML是一种常用的数据格式,用于在不同的系统之间传递和存储数据。本文通过阐述一个技术问题并给出解答的方式,介绍如何使用Python和正则表达式处理XML表单数据。我们将探讨整体设计、编写思…...

LA@方阵相似@相似矩阵的性质
文章目录 相似矩阵引言相似矩阵定义相似变换相似变换矩阵相似矩阵的矩阵多项式和特征值相同推论:与对角阵相似的矩阵性质定理 相似矩阵性质相似矩阵的乘方性质相似矩阵和矩阵多项式相似对角阵 对角阵多项式的展开小结 相似矩阵 引言 对角阵是矩阵中最简单的一类矩阵 对角阵相…...

ZLMediaKit 各种推拉流
1 用ffmpeg 推音视频流 ./ffmpeg -f dshow -i video"HP Wide Vision HD Camera" -f dshow -i audio"麦克风阵列 (Realtek High Definition Audio)" -rtbufsize 100M -max_delay 100 -pix_fmt yuv420p -tune zerolatency -c:v libx264 -crf 18 -s 1280x720…...

行业追踪,2023-08-29
自动复盘 2023-08-29 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...

【简单】228. 汇总区间
原题链接:https://leetcode.cn/problems/summary-ranges/description/ 228. 汇总区间 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖&…...

Mysql高级语句
高级语句 1.按关键字排序 SELECT column1, column2, ... FROM table_name ORDER BY column1, column2, ... ASC|DESC ASC 是按照升序进行排序的,是默认的排序方式,即 ASC 可以省略。 SELECT 语句中如果没有指定具体的排序方式,则默认按 ASC…...

Python中 re.compile 函数的使用
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 以下介绍在python的re模块中怎样应用正则表达式 👇 👇 👇 更多精彩机密、教程,尽在下方,赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备…...

【分布式搜索引擎es】
文章目录 数据搜索DSL实现查询文档搜索结果处理 RestClient实现 elasticsearch最擅长的是 搜索和 数据分析。 数据搜索 DSL实现 查询文档 常见的查询类型包括: 查询所有:查询出所有数据,一般测试用。例如:match_all全文检索…...

单片机的ADC
如何理解ADC。ADC就是将模拟量转换成数字量的过程,就是转换为计算机所能存储的0和1序列,比如将模拟量转换为一个字节,所以这个字节的大小要能反应模拟量的大小,比如一个0-5V的电压测量量(外部输入电压最小0V,最大为5V&…...

如何把pdf文件合并?分享最新pdf合并方法
在所有文档格式中,pdf应该是最常用的,像产品介绍、商务合同、法律文书等等,这些都是pdf格式的。有时候出于工作需要,我们要把两份或者多份pdf文件合并在一起,那么问题来了,如何把pdf文件合并呢?小编最近发…...

笙默考试管理系统-MyExamTest----codemirror(11)
笙默考试管理系统-MyExamTest----codemirror(11) 目录 笙默考试管理系统-MyExamTest----codemirror(11) 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试管…...

Spring MVC 五 - Spring MVC的配置和DispatcherServlet初始化过程
今天的内容是SpringMVC的初始化过程,其实也就是DispatcherServilet的初始化过程。 Special Bean Types DispatcherServlet委托如下一些特殊的bean来处理请求、并渲染正确的返回。这些特殊的bean是Spring MVC框架管理的bean、按照Spring框架的约定处理相关请求&…...

Ramp 有点意思的题目
粗一看都不知道这个要干什么,这 B 装得不错。 IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKJycnCktlZXAgdXMgb3V0IG9mIGdvb2dsZSBzZWFyY2ggcmVzdWx0cy4uCgokIG9kIC1kIC9kZXYvdXJhbmRvbSB8IGhlYWQKMDAwMDAwMCAgICAgNjAyMTUgICAyODc3OCAgIDI5MjI3ICAgMjg1NDggICA2MjY4NiAgIDQ1MT…...

算法通关村14关 | 堆在数组中找第k大的元素应用
1. 在数组中找第k大元素 题目 LeetCode215:给定整数数组nums和整数k,请返回数组中第k个最大的元素, 思路 解题思路用三个,选择法,堆查找和快速排序。 我们选择用大堆小堆解决问题,“找最大用小堆ÿ…...

Unity 顶点vertices,uv,与图片贴图,与mesh
mesh就是组成3d物体的三角形们。 mesh由顶点组成的三角形组成,三角形的大小 并不 需要一样,由顶点之间的位置决定。 mesh可以是一个或者多个面。 贴图的原点在左下角,uv是贴图的坐标,数量和顶点数一样(不是100%确定…...

Shell编程之函数
目录 基本概念 自定义函数 系统函数 1.read 2.basename 3.dirname 基本概念 将一段代码组合封装在一起实现某个特定的功能或返回某个特定的值,然后给这段代码取个名字,也就是函数名,在需要实现某个特定功能的时候直接调用函数名即可。 函…...

10.物联网LWIP之TCP状态转变
一。TCP状态机 1.青粗线:理想TCP状态转变(服务器视角下) 2.虚线:被动TCP状态转变(服务器视角下) 3.细实线:不经常出现的TCP状态转变(类似于边界处理) 1.青粗线解释--》服…...

Img标签的src地址自动拼接本地域名(localhost:8080)导致图片不显示问题
摘要:做Vueelement ui项目的时候,发现使用element ui的upload上传图片时,不显示的问题。我项目的图片是上传到七牛云,长传成功后返回存储在七牛云中的地址。后面发现是因为返回的地址是外部地址,需要完整的URL…...

数据结构入门 — 栈
本文属于数据结构专栏文章,适合数据结构入门者学习,涵盖数据结构基础的知识和内容体系,文章在介绍数据结构时会配合上动图演示,方便初学者在学习数据结构时理解和学习,了解数据结构系列专栏点击下方链接。 博客主页&am…...

Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录
Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录 目录 Unity Android 之 在Unity 中引入 OkHttp的操作注意(OKHttp4.xx- kotlin 的包)简单记录 一、简单介绍 二、OKHttp 4.xx 的 SDK 封装 aar 给 Unity 的使用注意 三、附录 OKHttp 的…...

内嵌功能强大、低功耗STM32WB55CEU7、STM32WB55CGU7 射频微控制器 - MCU, 48-UFQFN
一、概述: STM32WB55xx多协议无线和超低功耗器件内嵌功能强大的超低功耗无线电模块(符合蓝牙 低功耗SIG规范5.0和IEEE 802.15.4-2011标准)。该器件内含专用的Arm Cortex -M0,用于执行所有的底层实时操作。这些器件基于高性能Arm …...

【测试】笔试03
文章目录 1. 哪种测试模型把测试过程作为需求分析、概要设计、详细设计及编码之后的阶段( )2. 在下面所列举的逻辑测试覆盖中,测试覆盖最强的是?3. 网络管理员编写了shell程序prog1.sh,测试时程序死循环无法结束,可以通过下列方式…...

JavaScript的while和for循环
一、循环语句 1.认识循环 在开发中我们经常需要做各种各样的循环操作: 比如把一个列表中的商品、歌曲、视频依次输出进行展示;比如对一个列表进行累加计算;比如运行相同的代码将数字 1 到 10 逐个输出; 循环 是一种重复运行同…...

mqtt安卓客户端
1.MQTT(消息队列遥测传输协议),是一种基于 发布/订阅 (publish/subscribe)模式的"轻量级"通讯协议, 该协议构建于TCP/IP协议上 。MQTT最大优点在于,可以以极少的代码和有限的带宽&…...

pdf怎么删除其中一页?
pdf怎么删除其中一页?现在,pdf文件已经深入影响着我们的工作和学习,如果你是一个上班族,那么几乎每天都会使用到pdf格式的电脑文件。当我们阅读一个页数众多的PDF文件时,可能会发现实际上只需要其中的一小部分内容。很…...

10.Redis 渐进式遍历
Redis 渐进式遍历 渐进式遍历scan 渐进式遍历 keys 命令一次性的把整个redis中所有的key都获取到,keys *但这个操作比较危险,可能会一下子得到太多的key,阻塞 redis 服务器。 通过渐进式遍历,就可以做到,既可以获取到所有的 key&…...

字符函数和字符串函数(2)
目录 memcpy memmove memcmp memcpy void * memcpy ( void * destination, const void * source, size_t num ); 1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 2.这个函数在遇到 \0 的时候并不会停下来。 3.如果source和destination有…...

目录扫描+JS文件中提取URL和子域+403状态绕过+指纹识别(dirsearch_bypass403)
dirsearch_bypass403 在安全测试时,安全测试人员信息收集中时可使用它进行目录枚举,目录进行指纹识别,枚举出来的403状态目录可尝试进行绕过,绕过403有可能获取管理员权限。不影响dirsearch原本功能使用 运行流程 dirsearch进行…...

【UE 材质】常用向量运算节点——点积、叉积、归一化
目录 一、点积 二、叉积 三、归一化 一、点积 点积,也称为内积或数量积,是一种用于计算两个向量之间关系的操作。对于两个三维向量 A(a1,a2,a3)和 B(b1,b2,b3),它们的点积可以用以下公式表示: ABa1⋅…...