当前位置: 首页 > news >正文

Token相关设计

文章目录

    • 1. 双Token 机制概述
      • 1.1 访问令牌(Access Token)
      • 1.2 刷新令牌(Refresh Token)
    • 2. 双Token 认证流程
    • 3. Spring Boot 具体实现
      • 3.1 生成 Token(使用 JWT)
      • 3.2 解析 Token
      • 3.3 登录接口(返回双 Token)
      • 3.4 刷新 Token 接口
      • 3.5 退出登录
    • 4. 总结 🚀

在微服务架构中,Token 认证是保障系统安全性的重要手段,常见的方式包括 JWT(JSON Web Token)基于 Redis 的 Token 认证。本文将介绍 双Token 机制 及其具体实现。


1. 双Token 机制概述

1.1 访问令牌(Access Token)

  • 用途:前端每次请求携带该令牌,用于身份认证。
  • 有效期:较短(如10分钟 - 2小时)。
  • 存储方式:前端存储(如 LocalStorage、SessionStorage、HTTP Only Cookie)。
  • 信息载荷:用户 ID、权限、过期时间等。

1.2 刷新令牌(Refresh Token)

  • 用途:用于获取新的 Access Token,避免用户频繁登录。
  • 有效期:较长(如7天 - 30天)。
  • 存储方式:数据库或 Redis(不能存储在前端,防止滥用)。
  • 信息载荷:用户 ID,仅用于重新获取 Access Token。

2. 双Token 认证流程

  1. 用户登录

    • 用户提交用户名、密码。
    • 后端校验通过后,生成 Access Token(短期) 和 Refresh Token(长期)。
    • Access Token 通过 JWT 方式返回给前端
    • Refresh Token 存储到数据库或 Redis,避免前端篡改。
  2. 请求 API 资源

    • 前端在每次请求时,携带 Authorization: Bearer <Access Token>
    • 后端解析 Access Token,校验有效性。
    • 通过则返回资源,失败则根据错误码处理(如 401 Unauthorized)。
  3. Token 过期时的处理

    • Access Token 过期,但 Refresh Token 仍有效 :

      • 前端调用 刷新接口,携带 Refresh Token 请求新 Access Token。
      • 后端验证 Refresh Token 后,重新生成 Access Token 并返回。
    • Refresh Token 过期或无效:

      • 需要用户重新登录。
  4. 用户登出

    • 后端删除 Refresh Token 记录。
    • 前端删除 Access Token。

3. Spring Boot 具体实现

3.1 生成 Token(使用 JWT)

import io.jsonwebtoken.*;
import java.util.Date;public class JwtUtil {private static final String SECRET_KEY = "your_secret_key";private static final long ACCESS_TOKEN_EXPIRATION = 2 * 60 * 60 * 1000; // 2小时private static final long REFRESH_TOKEN_EXPIRATION = 7 * 24 * 60 * 60 * 1000; // 7天// 生成 Access Tokenpublic static String generateAccessToken(String userId) {return Jwts.builder().setSubject(userId).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}// 生成 Refresh Tokenpublic static String generateRefreshToken(String userId) {return Jwts.builder().setSubject(userId).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRATION)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}
}

3.2 解析 Token

public static Claims parseToken(String token) {return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}

3.3 登录接口(返回双 Token)

@RestController
@RequestMapping("/auth")
public class AuthController {@PostMapping("/login")public Map<String, String> login(@RequestBody LoginRequest request) {// 1. 校验用户名和密码(省略)// 2. 生成 TokenString accessToken = JwtUtil.generateAccessToken(request.getUsername());String refreshToken = JwtUtil.generateRefreshToken(request.getUsername());// 3. 存储 Refresh Token(示例使用 Redis)redisTemplate.opsForValue().set("refresh_token:" + request.getUsername(), refreshToken, 7, TimeUnit.DAYS);// 4. 返回 TokenMap<String, String> tokens = new HashMap<>();tokens.put("accessToken", accessToken);tokens.put("refreshToken", refreshToken);return tokens;}
}

3.4 刷新 Token 接口

@PostMapping("/refresh")
public ResponseEntity<Map<String, String>> refresh(@RequestHeader("Authorization") String refreshToken) {// 1. 校验 Refresh TokenClaims claims = JwtUtil.parseToken(refreshToken);String userId = claims.getSubject();// 2. 检查 Redis 是否存储该 Refresh TokenString storedToken = redisTemplate.opsForValue().get("refresh_token:" + userId);if (storedToken == null || !storedToken.equals(refreshToken)) {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();}// 3. 生成新的 Access TokenString newAccessToken = JwtUtil.generateAccessToken(userId);// 4. 返回新的 TokenMap<String, String> tokens = new HashMap<>();tokens.put("accessToken", newAccessToken);return ResponseEntity.ok(tokens);
}

3.5 退出登录

@PostMapping("/logout")
public ResponseEntity<Void> logout(@RequestHeader("Authorization") String accessToken) {Claims claims = JwtUtil.parseToken(accessToken);String userId = claims.getSubject();// 删除 Redis 中的 Refresh TokenredisTemplate.delete("refresh_token:" + userId);return ResponseEntity.ok().build();
}

4. 总结 🚀

机制作用过期时间存储位置
Access Token用于 API 认证短(10分钟-2小时)前端 LocalStorage/SessionStorage
Refresh Token用于刷新 Access Token长(7天-30天)Redis/数据库
  • 双 Token 机制 既保证了安全性(短期有效的 Access Token)又提升了用户体验(长期有效的 Refresh Token)。
  • Access Token 过期时,通过 Refresh Token 重新获取,而无需重新登录。
  • Refresh Token 需要存储在后端(如 Redis),避免前端泄露。

博客主页: 总是学不会.

相关文章:

Token相关设计

文章目录 1. 双Token 机制概述1.1 访问令牌&#xff08;Access Token&#xff09;1.2 刷新令牌&#xff08;Refresh Token&#xff09; 2. 双Token 认证流程3. Spring Boot 具体实现3.1 生成 Token&#xff08;使用 JWT&#xff09;3.2 解析 Token3.3 登录接口&#xff08;返回…...

【时序预测】在线学习:算法选择(从线性模型到深度学习解析)

——如何为动态时序预测匹配最佳增量学习策略&#xff1f; 引言&#xff1a;在线学习的核心价值与挑战 在动态时序预测场景中&#xff08;如实时交通预测、能源消耗监控&#xff09;&#xff0c;数据以流式&#xff08;Streaming&#xff09;形式持续生成&#xff0c;且潜在的…...

React antd的datePicker自定义,封装成组件

一、antd的datePicker自定义 需求&#xff1a;用户需要为日期选择器的每个日期单元格添加一个Tooltip&#xff0c;当鼠标悬停时显示日期、可兑换流量余额和本公会可兑流量。这些数据需要从接口获取。我需要结合之前的代码&#xff0c;确保Tooltip正确显示&#xff0c;并且数据…...

学生管理前端

文章目录 首页student.html查询功能 首页 SpringBoot前端html页面放在static文件夹下&#xff1a;/src/main/resources/static 默认首页为index.html&#xff0c;我们可以用两个超链接或者两个button跳转到对应的页面。这里只是单纯的跳转页面&#xff0c;不需要提交表单等其…...

深入理解并实现自定义 unordered_map 和 unordered_set

亲爱的读者朋友们&#x1f603;&#xff0c;此文开启知识盛宴与思想碰撞&#x1f389;。 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 在 C 的标准模板库&#xff08;STL&#xff09;中&#xff0c;unorder…...

顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-大模型电话机器人

语音流直接对接Realtime API 多模态大模型 直接把音频流输出给大模型&#xff0c;大模型返回音频流。 顶顶通CTI对Realtime API 的支持 提供了以下2个APP可对接任意 •cti_audio_stream 通过TCP推流和播放流&#xff0c;适合用于人机对话场景。 •cti_unicast_start 通过旁…...

kinova机械臂绿色灯一闪一闪及刷机方法

一、背景 实验室有两个kinova mico机械臂&#xff0c;但经常出现操纵杆上的绿色灯一闪一闪的&#xff0c;导致无法使用操纵杆或ROS进行控制&#xff0c;下面给出官方的教程以及所需要的FS 0CPP 0008_6.2.5_mico_6dof.hex文件。 重要的东西写在前面&#xff1a; a、如果出现操…...

第16天:C++多线程完全指南 - 从基础到现代并发编程

第16天&#xff1a;C多线程完全指南 - 从基础到现代并发编程 一、多线程基础概念 1. 线程创建与管理&#xff08;C11&#xff09; #include <iostream> #include <thread>void hello() {std::cout << "Hello from thread " << std::this_…...

中科大计算机网络原理 1.5 Internt结构和ISP

一、互联网的层次化架构 ‌覆盖范围分层‌ ‌主干网&#xff08;Tier-1级&#xff09;‌ 国家级或行业级核心网络&#xff0c;承担跨区域数据传输和全球互联功能。例如中国的四大主干网&#xff08;ChinaNET、CERNET等&#xff09;以及跨国运营商&#xff08;如AT&T、Deuts…...

Windows安装sql server2017

看了下官网的文档&#xff0c;似乎只有ubuntu18.04可以安装&#xff0c;其他debian系的都不行&#xff0c;还有通过docker的方式安装的。 双击进入下载的ISO&#xff0c;点击执行可执行文件&#xff0c;并选择“是” 不要勾选 警告而已&#xff0c;不必理会 至少勾选这两…...

计算机网络之传输层(tcp协议)

一、TCP协议的特点 面向连接&#xff1a;TCP使用面向连接的通信模式&#xff0c;通信双方需要先建立连接&#xff0c;然后才能进行数据的传输。连接建立过程采用三次握手的方式。 可靠性&#xff1a;TCP提供可靠的数据传输服务&#xff0c;确保数据的完整性、有序性和正确性。…...

从零到一:如何用阿里云百炼和火山引擎搭建专属 AI 助手(DeepSeek)?

本文首发&#xff1a;从零到一&#xff1a;如何用阿里云百炼和火山引擎搭建专属 AI 助手&#xff08;DeepSeek&#xff09;&#xff1f; 阿里云百炼和火山引擎都推出了免费的 DeepSeek 模型体验额度&#xff0c;今天我和大家一起搭建一个本地的专属 AI 助手。  阿里云百炼为 …...

Open3D解决SceneWidget加入布局中消失的问题

Open3D解决SceneWidget加入布局中消失的问题 Open3D解决SceneWidget加入布局中消失的问题1. 问题2. 问题代码3. 解决 Open3D解决SceneWidget加入布局中消失的问题 1. 问题 把SceneWidget加到布局管理其中图形可以展示出来&#xff0c;但是鼠标点击就消失了。 stackoverflow上已…...

计算机毕业设计Python+DeepSeek-R1大模型游戏推荐系统 Steam游戏推荐系统 游戏可视化 游戏数据分析(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Linux笔记---缓冲区

1. 什么是缓冲区 在计算机系统中&#xff0c;缓冲区&#xff08;Buffer&#xff09; 是一种临时存储数据的区域&#xff0c;主要用于协调不同速度或不同时序的组件之间的数据传输&#xff0c;以提高效率并减少资源冲突。它是系统设计中的重要概念&#xff0c;尤其在I/O操作、网…...

如何流畅访问github

1.传输数据原理 本地计算机通过本地网接入运营骨干网&#xff0c;经过DNS域名解析&#xff0c;将输入的字符解析为要连接的真实IP地址&#xff0c;服务器返还一个数据包(github)给计算机 2.原因 DNS域名污染-DNS解析出现问题&#xff0c;导致访问一个不存在的服务器 3.解决…...

java基础+面向对象

Java基础语法 CMD命令 cls 清屏 cd 目录进入文件 cd… 退回 dir 查看当前目录所有文件 E&#xff1a;进入E盘 exit 退出 环境变量就是不用去专门的盘符去找&#xff0c;直接去环境变量里找到文件 语言优势 编译型语言c&#xff1a; 整体翻译 解释型语言python&#x…...

Linux 检测内存泄漏方法总结

文章目录 strace检测asan内存检测linux下gperf工具&#xff08;tcmalloc&#xff09;检查C/C代码内存泄露问题参考 strace检测 &#xff08;1&#xff09;启动程序 &#xff08;2&#xff09; strace -f -p <PID> -tt -e brk,mmap,mmap2,munmapbrk 变大 → 说明堆增长…...

本地部署deepseek大模型后使用c# winform调用(可离线)

介于最近deepseek的大火&#xff0c;我就在想能不能用winform也玩一玩本地部署&#xff0c;于是经过查阅资料&#xff0c;然后了解到ollama部署deepseek,最后用ollama sharp NUGet包来实现winform调用ollama 部署的deepseek。 本项目使用Vs2022和.net 8.0开发&#xff0c;ollam…...

Python----数据分析(Numpy:安装,数组创建,切片和索引,数组的属性,数据类型,数组形状,数组的运算,基本函数)

一、 Numpy库简介 1.1、概念 NumPy(Numerical Python)是一个开源的Python科学计算库&#xff0c;旨在为Python提供 高性能的多维数组对象和一系列工具。NumPy数组是Python数据分析的基础&#xff0c;许多 其他的数据处理库&#xff08;如Pandas、SciPy&#xff09;都依赖于Num…...

机器学习辅助第一性原理:高精度计算电化学氧化还原电位

1. 项目概述&#xff1a;当机器学习遇上第一性原理&#xff0c;破解电化学模拟的精度瓶颈在电化学、材料科学和计算化学的交叉领域&#xff0c;预测一个分子或离子在溶液中的氧化还原电位&#xff0c;就像试图在暴风雨中测量一滴雨滴的精确落点。这个数值&#xff0c;直接决定了…...

机器学习赋能系统综述:SyROCCo项目实战解析与NLP应用指南

1. 项目概述&#xff1a;当系统综述遇上机器学习如果你做过系统综述&#xff0c;一定对那种“望洋兴叹”的感觉不陌生。面对动辄成千上万的文献&#xff0c;光是筛选、阅读、提取数据这几步&#xff0c;就足以耗掉一个团队数月甚至数年的精力。更头疼的是&#xff0c;等你终于完…...

软体机器人跳跃:离散弹性杆仿真与动态分岔原理详解

1. 软体机器人跳跃&#xff1a;从生物灵感走向工程现实如果你观察过一只蚂蚱的起跳&#xff0c;或者一只青蛙的弹射&#xff0c;那种瞬间爆发、姿态优雅的运动&#xff0c;背后是自然界亿万年来优化的高效能量转换机制。传统的刚性机器人&#xff0c;靠着电机、齿轮和连杆&…...

【芯片测试】:6. 向量、Sequencer 指令与高速串行 IO

Pattern 详解&#xff1a;向量、Sequencer 指令与高速串行 IO系列&#xff1a; Advantest V93000 SmarTest 8 核心概念解析&#xff5c;第 6 篇&#xff08;共 8 篇&#xff09; 适合读者&#xff1a; 需要理解数字测试激励数据结构的工程师前言 Pattern&#xff08;模式&#…...

反事实推理:用因果视角评估与缓解AI模型偏见

1. 项目概述&#xff1a;当模型决策需要“如果当初”在机器学习的世界里&#xff0c;我们常常面临一个困境&#xff1a;模型预测准确率很高&#xff0c;但我们却不知道它为什么做出这样的决策。更棘手的是&#xff0c;我们越来越频繁地发现&#xff0c;这些“黑箱”决策背后&am…...

从零到一:用 LangChain 搭建你的第一个 AI Agent,让 LLM 自己干活!

导读&#xff1a;&#xff0c;2024年最火的不是大模型本身&#xff0c;而是基于大模型的 AI Agent。它能自主思考、调用工具、执行任务——不再是"你说一句我回一句"的聊天机器人&#xff0c;而是真正能帮你干活的数字员工。本文从零带你搭建一个完整的 AI Agent&…...

在VirtualBox里跑Win10,远程桌面连不上?试试这个被忽略的虚拟机专用配置

VirtualBox虚拟机Win10远程桌面黑屏&#xff1f;这个隐藏配置项可能是关键在混合开发环境中&#xff0c;许多技术从业者习惯使用VirtualBox等虚拟化工具搭建多操作系统平台。一个常见场景是在Windows 7宿主机上运行Windows 10虚拟机&#xff0c;通过远程桌面进行跨系统操作。但…...

大语言模型作为人类行为研究工具:从原理到实践

1. 从“模仿”到“理解”&#xff1a;AI研究范式的悄然转向最近和几位做社会学和心理学研究的朋友聊天&#xff0c;发现一个挺有意思的现象&#xff1a;他们实验室的电脑屏幕上&#xff0c;除了SPSS、R语言的分析窗口&#xff0c;越来越多地出现了像ChatGPT、Claude这样的对话界…...

Rust异步编程实战:构建高性能并发应用

引言 异步编程是构建高性能后端服务的关键技术。作为从Python转向Rust的开发者&#xff0c;我发现Rust的异步模型与Python有很大不同。Rust的异步编程基于协程和事件驱动&#xff0c;通过Tokio运行时实现高效的并发执行。本文将深入探讨Rust异步编程的核心概念、实践模式和性能…...

实测天下工厂:用它找工厂客户,数据准不准、覆盖全不全?

做 B2B 销售的人都知道&#xff0c;找到一份"高质量工厂名单"有多难。 不是因为工厂数量少&#xff0c;而是因为现有渠道普遍存在一个结构性问题&#xff1a;工厂和非工厂混在一起&#xff0c;分不清楚。用通用企业查询工具检索某个行业&#xff0c;跑出来的结果里&a…...