【全栈】SprintBoot+vue3迷你商城-细节解析(1):Token、Jwt令牌、Redis、ThreadLocal变量

news/2025/2/21 6:57:35

【全栈】SprintBoot+vue3迷你商城-细节解析(1):Token、Jwt令牌、Redis、ThreadLocal变量

往期的文章都在这里啦,大家有兴趣可以看一下

后端部分:

【全栈】SprintBoot+vue3迷你商城(1)
【全栈】SprintBoot+vue3迷你商城(2)
【全栈】SprintBoot+vue3迷你商城-扩展:利用python爬虫爬取商品数据
【全栈】SprintBoot+vue3迷你商城(3)
【全栈】SprintBoot+vue3迷你商城(4)
【全栈】SprintBoot+vue3迷你商城(5)
【全栈】SprintBoot+vue3迷你商城(6)

前端部分:

【全栈】SprintBoot+vue3迷你商城-扩展:vue的基本用法

【全栈】SprintBoot+vue3迷你商城-扩展:vue3项目创建及目录介绍

【全栈】SprintBoot+vue3迷你商城(7)

【全栈】SprintBoot+vue3迷你商城(8)

【全栈】SprintBoot+vue3迷你商城(9)

【全栈】SprintBoot+vue3迷你商城(10)

文章目录

  • 【全栈】SprintBoot+vue3迷你商城-细节解析(1):Token、Jwt令牌、Redis、ThreadLocal变量
    • 1.是什么及其联系
      • Token 和 JWT 令牌
      • Redis
      • ThreadLocal 变量
      • 它们之间的联系
    • 2.在该项目中的应用
      • 2.1.配置
        • Redis
        • JWT令牌以及ThreadLocal工具类
    • 2.2.应用
    • 3.总结

1.是什么及其联系

Token、JWT令牌(JSON Web Token)、Redis和ThreadLocal变量在现代Web应用程序中常常被结合使用,尤其是在涉及用户认证与授权、会话管理以及并发处理等方面。下面解释它们之间的联系:

Token 和 JWT 令牌

  • Token:是一种用于标识用户身份的数据片段,通常是在用户成功登录后由服务器生成并返回给客户端。客户端随后会在每次请求时将这个token附带在请求头或请求参数中发送回服务器以证明其身份。
  • JWT (JSON Web Token):是一种特定类型的token格式,它允许你在一个紧凑且自包含的字符串中安全地传输信息作为JSON对象。JWT通常由三部分组成:Header(头部)、Payload(负载)和Signature(签名)。JWT可以用来存储用户的认证信息,并且由于其具备签名特性,接收方能够验证内容是否被篡改。

Redis

  • Redis:是一个开源的内存数据结构存储系统,常被用作数据库、缓存和消息中间件。在Web应用中,Redis可以用来存储session数据或JWT令牌,以便快速访问和验证。例如,当用户登录时,可以生成一个JWT并将之存储在Redis中,同时设置过期时间。这样,后续请求只需查询Redis即可验证token的有效性,而无需每次都查询数据库。

ThreadLocal 变量

  • ThreadLocal:提供线程局部变量,每个使用该变量的线程都会拥有独立的副本,从而避免了多线程环境下的资源共享问题。在Web应用中,ThreadLocal变量可用于保存当前请求上下文中的某些状态信息,比如当前登录用户的详细信息等。这使得在整个请求生命周期内,这些信息可以在任何地方方便地获取,而不需要通过方法参数传递。

它们之间的联系

  1. 认证过程
    • 用户登录成功后,服务器生成一个JWT令牌,并可能将其存储在Redis中(为了便于管理和撤销),然后将此JWT返回给客户端。
  2. 请求处理
    • 当客户端发起请求时,会携带JWT令牌。服务器接收到请求后,首先从请求头中提取出JWT。
    • 接着,服务器可能会先检查Redis来确认JWT是否有效(如是否存在、是否已过期等)。如果Redis中存在该JWT,则继续处理请求;否则,可能需要重新登录或其他操作。
  3. 并发控制与安全性
    • 在请求处理过程中,为了保证线程安全,可以使用ThreadLocal变量来保存一些临时性的状态信息,比如当前请求解析出来的用户ID或者权限列表。这样做可以让这些信息在线程内部随时可用,同时也避免了多线程环境下可能出现的数据竞争问题。
  4. 性能优化
    • 使用Redis存储JWT令牌可以显著提高验证速度,因为Redis是基于内存的存储系统,查找速度远快于传统的数据库查询。
    • ThreadLocal变量则有助于减少不必要的对象传递,简化代码逻辑,特别是在复杂的业务场景下,能有效地提升开发效率和程序执行效率。

所以,Token(特别是JWT)用于用户的身份验证和授权,Redis用于高效地存储和检索这些令牌,而ThreadLocal变量则为单个请求线程提供了便捷的状态管理方式。三者结合起来,可以构建既安全又高效的Web服务架构。

2.在该项目中的应用

2.1.配置

使用它们之前首先要去配置它们,我们在application.yml进行Redis的配置,然后编写JWT令牌以及ThreadLocal的工具类

Redis
# application.yml
spring:
  data:
    redis:
      port: 6379
      host: localhost
JWT令牌以及ThreadLocal工具类

JwtUtil:

java">// JwtUtil

package com.janium.minimallbe.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;
import java.util.Map;

public class JwtUtil {

    private static final String KEY = "itheima";
	
	//接收业务数据,生成token并返回
    public static String genToken(Map<String, Object> claims) {
        return JWT.create()
                .withClaim("claims", claims)
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))
                .sign(Algorithm.HMAC256(KEY));
    }

	//接收token,验证token,并返回业务数据
    public static Map<String, Object> parseToken(String token) {
        return JWT.require(Algorithm.HMAC256(KEY))
                .build()
                .verify(token)
                .getClaim("claims")
                .asMap();
    }

}

ThreadLocalUtil:

java">package com.janium.minimallbe.utils;

/**
 * ThreadLocal 工具类
 */
@SuppressWarnings("all")
public class ThreadLocalUtil {
    //提供ThreadLocal对象,
    private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();

    //根据键获取值
    public static <T> T get(){
        return (T) THREAD_LOCAL.get();
    }
	
    //存储键值对
    public static void set(Object value){
        THREAD_LOCAL.set(value);
    }


    //清除ThreadLocal 防止内存泄漏
    public static void remove(){
        THREAD_LOCAL.remove();
    }
}

2.2.应用

我们登录时应该生成一个token,而生成token可以交给Jwt工具类,然后我们需要将生成的token储存在redis中。而且,为了方便直接获取到用户Id等信息,我们可以将token中的信息存储到ThreadLocal变量中。

UserController:

java">@PostMapping("/login")
    public Result login(
            @Pattern(regexp = "^\\S{6,18}$") String username,
            @Pattern(regexp = "^\\S{6,18}$") String password
    ){
        User u = userService.findByName(username);
        if(u == null){
            return Result.error("用户名错误");
        }
        if (u.getPassword().equals(Md5Util.getMD5String(password))) {
            // 1.设置token并将其储存到redis

            Map<String, Object> claims = new HashMap<>();
            claims.put("id", u.getId());
            claims.put("username", username);
            String token= JwtUtil.genToken(claims);
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); // redis模板接口
            operations.set(token,token,12, TimeUnit.HOURS); // 将token存储到redis

            return Result.success(token);
        }
        return Result.error("密码错误!");
    }

LoginInterceptor:

java">try {
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            String redisToken = operations.get(token);
            if (redisToken == null) {
                throw new RuntimeException();
            }
            Map<String, Object> claims = JwtUtil.parseToken(token);
            // 1.如果登录成功则将token里的信息存入ThreadLocal变量中,以便后续使用
            ThreadLocalUtil.set(claims);
            return true;
        } catch (Exception e) {
            response.setStatus(401);
            return false;
        }

    }

3.总结

本期为细节解析期的第一期,补充了TokenJwt令牌、RedisThreadLocal变量等细节,下期将继续补充开发中的一些细节问题。


http://www.niftyadmin.cn/n/5860413.html

相关文章

Python C API 深度解析与实战指南

本文聚焦于 Python C API&#xff0c;全面介绍其核心内容&#xff0c;包括基本概念、对象操作、类型系统、模块和导入机制、内存管理、线程安全等方面。通过深入剖析每个部分&#xff0c;结合详细的代码示例和图文讲解&#xff0c;帮助开发者掌握使用 Python C API 在 C 语言中…

定期自动统计大表执行情况

一、创建用户并赋权 create user dbtj identified by oracle default tablespace OGGTBS;grant connect,resource to dbtj;grant select any dictionary to dbtj;grant create job to dbtj;grant manage scheduler to dbtj; 二、创建存储表 1、连接到新建用户 conn dbtj/or…

风险价值VaR、CVaR与ES

风险价值VaR、CVaR与ES 一、VaR风险价值1. VaR的定义及基本概念2.VaR的主要性质3.风险价值的优缺点 二、CVaR条件风险价值与ES预期损失1.CVaR的基本概念2.性质3.ES预期损失 一、VaR风险价值 1. VaR的定义及基本概念 20年前&#xff0c;JP的大佬要每天下午收盘后的4:15在桌上看…

游戏引擎学习第114天

打开内容并回顾 目前正在讨论一个非常重要的话题——优化。当代码运行太慢&#xff0c;无法达到所需性能时&#xff0c;我们该怎么办。昨天&#xff0c;我们通过在代码中添加性能计数器&#xff0c;验证了一些性能分析的数据&#xff0c;这些计数器帮助我们了解每个操作需要的…

docker 改了镜像源为阿里云,还是下载失败

我是windows系统&#xff0c;在学习docker&#xff0c;刚开始执行docker run hello-world还是失败&#xff0c;然后改了镜像源为阿里云&#xff0c;还是失败&#xff0c;后来去查资料&#xff0c;除了阿里云还配置了很多其他镜像源&#xff0c;才好使 "registry-mirrors&q…

TOGAF之架构标准规范-信息系统架构 | 应用架构

TOGAF是工业级的企业架构标准规范&#xff0c;信息系统架构阶段是由数据架构阶段以及应用架构阶段构成&#xff0c;本文主要描述信息系统架构阶段中的应用架构阶段。 如上所示&#xff0c;信息系统架构&#xff08;Information Systems Architectures&#xff09;在TOGAF标准规…

源码方式安装llama.cpp及调试

llama.cpp源码方式安装和调试配置 构建和编译 注意这里是cuda&#xff0c;且要开启debug模式 cmake -B build -DGGML_CUDAON -DCMAKE_BUILD_TYPEDebug cmake --build build --config Debug正在编译&#xff1a; 配置launch.json用于调式&#xff1a; 要根据自己的环境路径…

【Java】代理模式

代理模式 代理模式是指给某一个对象提供一个代理&#xff0c;并由代理对象来控制对真实对象的访问 代理模式是一种结构型设计模式 背景 如果不采用代理&#xff0c;对一个类的多个方法进行监控时&#xff0c;重复的代码总是重复出现&#xff0c;不但破坏了原方法&#xff0c;…