Threadlocal+拦截器+JWT实现登录

news2024/11/15 5:54:59

很多数据库表都会有创建时间和修改时间,这个可以用mp的自动填充来实现。

也有修改人和更新人的字段,用户登录进来后,修改数据如何拿到修改人呢?每次操作不能把操作人的信息都携带者,那么如何拿到修改人的数据,主要是需要拿到id。

JWT

http协议本身是一种无状态的协议,如果用户向服务器提供了用户名和密码来进行用户认证,下次请求时,用户还要再一次进行用户认证才行。因为根据http协议,服务器并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储─份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样应用就能识别请求来自哪个用户

JWT JSON Web Token(JSON Web令牌)
是一个开放标准(rfc7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地传输信息。此信息可以验证和信任,因为它是数字签名的。jwt可以使用秘密〈使用HNAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

JWT作用:
授权:一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。它的开销很小并且可以在不同的域中使用。如:单点登录。
信息交换:在各方之间安全地传输信息。JWT可进行签名(如使用公钥/私钥对),因此可确保发件人。由于签名是使用标头和有效负载计算的,因此还可验证内容是否被篡改。

image.png
image.png

后端将token传给前端的时候,放入了id进去。前端再次访问的时候可以拿到用户的id。后端通过拦截器拦截。

JWT封装成工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

public class JwtUtil {
    //将密钥 和数据加密生产token

    //创建token 三个参数   密钥  过期时间   需要保存的数据
    public static String createJWT(String secretKey, long ttlMills, Map<String, Object> claims) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long expMills = System.currentTimeMillis() + ttlMills; //存储时间
        Date exp = new Date(expMills); //时间转为date
        JwtBuilder builder = Jwts.builder()
                .setClaims(claims)  //载荷
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                .setExpiration(exp); //过期时间
        return builder.compact(); // 变为字符串
    }

    /*
    根据token解析得到里面的数据
     */
    public static Claims parseJWT(String secretKey, String token) {
       try {
           Claims claims = Jwts.parser().setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                   .parseClaimsJws(token).getBody();
           return claims;
       }catch (Exception e){
           throw new RuntimeException("token失效");
       }
    }
}

密钥和时间配置存在application.yml文件中

@Data
@Component
@ConfigurationProperties(prefix = "shop.jwt")
public class JwtProperties {
    private String secret; // 密钥
    private int expire; // 过期时间(分钟)
}
shop:
  jwt:
    secret: njitzx
    expire: 60480000

拦截器

拦截器是SpringMVC下面的。

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/captchaLogin",
                        "/captchaImage", "/login","/alipay/notify");
    }
}
通过实现 WebMvcConfigurer 接口配置 Spring MVC。
将 LoginInterceptor 添加到拦截器注册表中,使其拦截所有进入的请求,
除了那些在 excludePathPatterns 中指定的路径(如登录接口、验证码接口等)。

package com.njitzx.interceptor;


import com.njitzx.exception.LoginErrorException;
import com.njitzx.properties.JwtProperties;
import com.njitzx.util.BaseContext;
import com.njitzx.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
@RestController                        //实现拦截器的接口
public class LoginInterceptor implements HandlerInterceptor {
          //请求之前拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进行登录拦截器");
        //
        if (!(handler instanceof HandlerMethod)){
            return  true;
        }
        简单来说,这个条件检查确保了只有那些由控制器方法(HandlerMethod)处理的请求才会被
        拦截器进一步处理。对于静态资源、错误页面、自定义处理器等非控制器方法处理的请求,
        拦截器会自动放行,不进行额外的拦截操作。
        String token = request.getHeader("Authorization"); //从请求头中拿到token
        try {
            Claims claims = JwtUtil.parseJWT("njitzx", token);
            Integer id = claims.get("id", Integer.class);
            BaseContext.setCurrentId(id); 
            System.out.println("用户的id" + id);
            return true;
        }catch (Exception ex){
            //如果返回 直接返回401
            response.setStatus(401);
            return  false;
        }
    }
}
  • 实现了 HandlerInterceptor 接口,重点实现了 preHandle 方法。
  • preHandle 方法会检查请求头中是否有一个有效的 JWT。
  • 如果 token 有效,会提取用户的 ID 并存储到 BaseContext 中以供后续使用。
  • 如果 token 无效或缺失,则将响应状态设置为 401 Unauthorized,并阻止请求继续处理。

Threadlocal

ThreadLocal叫做_线程变量,意思是ThreadLocal中填充的变量_属于**当前线程**,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

每个用户进来之后的threadLocal存储的值都是不一样的,具有隔离的特性。

public class BaseContext {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Integer id) {
        threadLocal.set(id);
    }

    public static Integer getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }
}

在拦截器那边通过token拿到id,并存入到threadlocal

Integer id = claims.get("id", Integer.class);
BaseContext.setCurrentId(id); 

登进系统之后需要根据根据不同的人显示不同的菜单,如何表示当前的用户呢,请求的时候走拦截器可以拿到id。
image.png

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

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

相关文章

数学建模赛前备赛——模拟退火算法

一.什么是智能优化算法 智能优化算法本质上是一个优化算法,它通过不断优化模型的参数,使得系统表现达到最优&#xff0c;常见的只能优化算法有很多&#xff0c;比如说蚁群算法,遗传算法以及我们今天的主角——模拟退火算法。 二.模拟算法的前身——爬山算法 爬山算法是一种简…

【Python入门】第1节 基础语法

&#x1f4d6;第1节 基础语法 ✅字面量✅注释✅变量✅数据类型&#x1f9ca;数据类型转换 ✅标识符✅运算符✅字符串扩展&#x1f9ca;字符串的三种定义方式&#x1f9ca;字符串拼接&#x1f9ca;字符串格式化&#x1f9ca;格式化的精度控制&#x1f9ca;字符串格式化方式2&…

equals与== 区别,全面总结如何使用(Java)

先理解JVM内存模型 虚拟机栈&#xff1a;JVM 运行过程中存储当前线程运行方法所需的数据&#xff0c; 指令、 返回地址本地方法栈&#xff1a;Java程序自动调用底层C/C函数库程序计数器&#xff1a;当前线程执行的字节码的行号指示器堆&#xff1a;存放我们申请的对象&#xff…

【Python 千题 —— 基础篇】入门异常处理

Python 千题持续更新中 …… 脑图地址 👉:⭐https://twilight-fanyi.gitee.io/mind-map/Python千题.html⭐ 题目描述 题目描述 编写一个程序,要求在处理用户输入时捕获各种异常情况,并为每种异常提供相应的处理方式。具体要求如下: 定义一个函数 divide_numbers(),它接…

php mail函数配置SMTP服务器发邮件的指南!

php mail函数安全性考虑&#xff1f;PHP mail()函数漏洞利用技巧&#xff1f; 在使用PHP进行开发时&#xff0c;发送邮件是一个常见的需求。使用php mail函数配置SMTP服务器发邮件&#xff0c;则是实现这一需求的有效途径。AokSend将详细探讨如何通过php mail函数来配置SMTP服…

Density-invariant Features for Distant Point Cloud Registration 论文解读

目录 一、导言 二、先导知识 1、FCGF 三、相关工作 1、深度学习的点云配准 2、对抗密度变化的方法 3、对比学习 四、GCL方法 1、U型曲线假设 一、导言 该论文来自于ICCV2023&#xff0c;上海交通大学提出的基于组对比学习的方案&#xff0c;来提取密度不变的几何特征&…

【终端IDPS】开源安全平台Wazuh之Wazuh Server

引言 Wazuh是一个开源的、免费的企业级安全监控解决方案&#xff0c;专注于威胁检测、完整性监控、事件响应和合规性。它由部署在受监控系统的端点安全代理和管理服务器组成&#xff0c;服务器收集并分析代理收集的数据。Wazuh支持多平台&#xff0c;包括Windows、Linux、macOS…

Linux学习笔记4 重点!网络排障命令

网络排障命令 命令行下载工具wget wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.20.17.tar.gz wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.20.17.tar.gz 限速下载 wget --limit-rate1M https://mirrors.edge.kernel.or…

【已解决】Vue Duplicate keys detected: ‘[object Object]’

【已解决】Vue Duplicate keys detected: ‘[object Object]’ 在Vue项目开发过程中&#xff0c;我们可能会遇到这样的报错&#xff1a;“Duplicate keys detected: ‘[object Object]’. This may cause an update error.”。这个错误通常发生在Vue的虚拟DOM进行渲染更新时&a…

上书房信息咨询:医疗满意度调研

随着人们生活水平的不断提高&#xff0c;医疗服务的需求日益增长。近期&#xff0c;上书房信息咨询受托完成了某市医疗市场的满意度调研&#xff0c;旨在深入了解市民对医疗服务的评价和需求&#xff0c;为提升医疗服务质量提供有力支持。 近年来&#xff0c;某市致力于推进医…

鸿蒙ArkTS语言学习(五):扩展(函数)@Extend@Styles@Builder

如何实现结构、样式复用呢&#xff1f; Extend&#xff1a;扩展组件&#xff08;样式、事件&#xff09; 作用&#xff1a;将相同组件复用的属性结构抽取封装&#xff0c;将不同的结构通过传入参数进行修改。 1. 定义语法 Extend(组件名) function 函数名{ ... } 2. 调用 组件…

一起学习LeetCode热题100道(60/100)

60.单词搜索(学习) 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那…

selenium消除启动特征避免被反爬-使用已经打开的浏览器

selenium消除启动特征避免被反爬 启动特征很多&#xff0c;如何消除selenium启动特征呢&#xff1f;这个也是因站而异&#xff0c;如果规避常规的检测&#xff0c;做到以下2点就可以。 1 是消除window.navigator.webdriver的值&#xff1b; 2 是修改chromedriver.exe的源码…

鸿蒙开发 数组改变,ui渲染没有刷新

问题描述&#xff1a; 数组push, 数组长度改变&#xff0c;ui也没有刷新 打印出了数组 console.log(this.toDoData.map(item > ${item.name}).join(, ), this.toDoData.length) 原代码&#xff1a; Text().fontSize(36).margin({ right: 40 }).onClick(() > {TextPicker…

在SpringBoot项目中使用多线程(配合线程池)加快从MySQL导入数据到ElasticSearch的速度

文章目录 1. 准备工作1.1 索引库1.2 建表1.3 实体类1.3.1 item.java1.3.2 itemDocument.java 1.4 编写配置文件1.5 编写 Mapper 类和 Service 类 2. 没有使用多线程的情况2.1 编码2.2 测试结果 3. 使用多线程&#xff08;配合线程池&#xff09;的情况3.1 自定义类&#xff0c;…

EM-7肽;EM-7-NH2;CAS:289632-61-7

【EM-7 简介】 EM-7&#xff0c;也被称为EM-7-NH2&#xff0c;其化学名称为[D-Glu5,D-Trp7,9,10]-Substance P (5-11)&#xff0c;分子式为C57H66N12O10S&#xff0c;分子量为1111.273。 【中文名称】(D-谷氨酰 5,D-色氨酰 7,9,10)-物质 P (5-11) 【英文名称】(D-Glu5,D-Trp7…

openlayers+vite+vue3实现规划某一特定行政区(二)

在前一期实现离线地图初始化的基础上&#xff0c;本文中主要阐述如何实现规划某一特定行政区&#xff0c;并展示其行政区的区县名称。 提示&#xff1a;因前文中阐述了如何实现离线地图的初始化&#xff0c;所以在此不再进行书写并详解初始化的过程和流程&#xff0c;如有不明…

Task-Embedded Control Networks for Few-Shot Imitation Learning

发表时间&#xff1a;CoRL 2018 论文链接&#xff1a;https://readpaper.com/pdf-annotate/note?pdfId4500197057754718210&noteId2424798567891365120 作者单位&#xff1a;Imperial College London Motivation&#xff1a;就像人类一样&#xff0c;机器人应该能够利用来…

力扣经典题目之->另一颗树的子树(subRoot是否是root的子树)

一&#xff1a;题目 本题需要用到力扣经典题目之-&#xff1e;相同的树&#xff08;递归判断两颗二叉树是否相同&#xff09;-CSDN博客 中的isSameTree&#xff0c;直接cv即可。 二&#xff1a;代码 三&#xff1a;解释 第一个函数&#xff1a; 力扣经典题目之-&#xff1e;相…

模型 分形理论

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。自相似&#xff0c;无限细节。 1 分形理论的应用 1.1 字节跳动的分形创新增长引擎 字节跳动作为一家全球领先的科技公司&#xff0c;其快速的发展和创新能力在业界引起了广泛关注。公司通过分形创新…