JWT和网关双令牌登录验证

使用JWT(JSON Web Token)和网关实现双令牌登录验证是一种安全性较高的方案。双令牌通常包括一个短期有效的访问令牌(access token)和一个长期有效的刷新令牌(refresh token)。以下是如何在Spring Boot项目中使用JWT和网关实现双令牌登录验证的步骤:

1. 设计令牌生成与验证策略

  • 访问令牌(Access Token):访问令牌是一个短期有效的JWT,它包含用户的身份信息和权限。访问令牌通常用于保护API端点,以确保只有授权用户才能访问。
  • 刷新令牌(Refresh Token):刷新令牌是一个长期有效的令牌,它用于在访问令牌过期后获取新的访问令牌。刷新令牌通常比访问令牌更安全,因为它只用于刷新令牌,不用于访问API。

2. 引入依赖

Maven依赖:

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Spring Cloud Gateway --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- JWT依赖 --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency>
</dependencies>

3. 生成和验证JWT

定义一个类,用于生成和验证JWT。可以使用JJWT库来处理JWT:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;public class JwtUtils {private static final String SECRET_KEY = "your-secret-key";private static final long ACCESS_TOKEN_EXPIRY = 5 * 60 * 1000; // 5分钟private static final long REFRESH_TOKEN_EXPIRY = 30 * 24 * 60 * 1000; // 30天// 生成访问令牌public static String generateAccessToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRY)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}// 生成刷新令牌public static String generateRefreshToken(String username) {return Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRY)).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}// 验证令牌public static String verifyToken(String token) {try {return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();} catch (Exception e) {return null; // 验证失败}}
}

这个类负责生成访问令牌和刷新令牌,以及验证令牌。

4. 在登录接口中使用JWT

在登录接口中,验证用户的凭证(例如用户名和密码),如果验证成功,生成访问令牌和刷新令牌,并将它们返回给客户端。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AuthController {@PostMapping("/login")public ResponseEntity<Map<String, String>> login(@RequestBody LoginRequest loginRequest) {// 验证用户凭证(例如用户名和密码)// 假设验证通过// 生成访问令牌和刷新令牌String accessToken = JwtUtils.generateAccessToken(loginRequest.getUsername());String refreshToken = JwtUtils.generateRefreshToken(loginRequest.getUsername());// 返回令牌Map<String, String> tokens = new HashMap<>();tokens.put("accessToken", accessToken);tokens.put("refreshToken", refreshToken);return ResponseEntity.ok(tokens);}
}

5. 在网关中验证访问令牌

在Spring Cloud Gateway中使用自定义过滤器来验证访问令牌:

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Configuration
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 从请求头中获取令牌String token = exchange.getRequest().getHeaders().getFirst("Authorization");// 验证令牌String username = JwtUtils.verifyToken(token);if (username == null) {// 令牌验证失败exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}// 令牌验证成功,继续处理请求return chain.filter(exchange);}@Overridepublic int getOrder() {return -1; // 设置过滤器优先级}
}

这个过滤器会在请求到达网关时验证访问令牌。如果令牌无效或缺失,过滤器会返回HTTP 401 Unauthorized响应;否则,继续处理请求。

6. 刷新令牌

你可以提供一个接口,用于根据刷新令牌获取新的访问令牌。这通常是在访问令牌过期后客户端请求的。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TokenController {@PostMapping("/refresh")public ResponseEntity<String> refresh(@RequestBody Map<String, String> request) {String refreshToken = request.get("refreshToken");String username = JwtUtils.verifyToken(refreshToken);if (username == null) {// 刷新令牌验证失败return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();}// 生成新的访问令牌String newAccessToken = JwtUtils.generateAccessToken(username);return ResponseEntity.ok(newAccessToken);}
}

总结:

通过以上步骤,你可以使用JWT和网关实现双令牌登录验证。该方案通过访问令牌保护API端点,通过刷新令牌获取新的访问令牌,提高了安全性和用户体验。在生产环境中,记得对JWT的密钥和配置进行妥善管理。

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

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

相关文章

C语言进阶课程学习记录-第36课 - 函数与指针分析

C语言进阶课程学习记录-第36课 - 函数与指针分析 函数类型实验-函数指针实验-回调机制小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 函数类型 实验-函数指针 #include <stdio.h>typedef in…

PLC工业网关,实现PLC联网

在当今工业自动化领域&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为控制系统的核心&#xff0c;其稳定性和可靠性至关重要。然而&#xff0c;随着工业互联网和智能制造的快速发展&#xff0c;如何实现PLC的联网通信&#xff0c;提高数据传输效率&#xff0c;成…

[蓝桥杯 2023 省 A] 更小的数(dp基础应用)

来源 洛谷P9232 本题dp思想 dp主要思想是&#xff1a;在同一类问题模型下&#xff0c;依赖于已经解决的简单问题基础上&#xff0c;用很小的代价获得更复杂一点的问题的解决方案。 有的题的DP是在下标上顺序性递推的&#xff0c;类似于dp[i]dp[i-1]something&#xff1b; 然…

Redis教程——数据类型(哈希、集合)

上篇文章我们学习了Redis教程——数据类型&#xff08;字符串、列表&#xff09;&#xff0c;这篇文章学习Redis教程——数据类型&#xff08;哈希表、集合&#xff09; 哈希表Hash 哈希表是一个string类型的field(字段)和value(值)的映射表&#xff0c;hash特别适合用于存储…

C语言进阶课程学习记录-函数指针的阅读

C语言进阶课程学习记录-函数指针的阅读 5个标识符含义解析技巧 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 5个标识符含义解析 int (*p1) (int* , int (*f) ( int* ) );定义了指针p1,指向函数&#…

OpenHarmony实战开发-如何通过分割swiper区域,实现指示器导航点位于swiper下方的效果。

介绍 本示例介绍通过分割swiper区域&#xff0c;实现指示器导航点位于swiper下方的效果。 效果预览图 使用说明 1.加载完成后swiper指示器导航点&#xff0c;位于显示内容下方。 实现思路 1.将swiper区域分割为两块区域&#xff0c;上方为内容区域&#xff0c;下方为空白区…

采用等价类划分法设计测试用例

例题1 请采用等价类划分法设计测试用例。 考虑软件 app, 它有两个输入变量 , 分别是 name 和 age, 其中 ,name 是至多包含 20 个字母字符的非空字符串 ,age 是整数型变量 ,0 ≤ age ≤ 120 。当输入给 name 的字符串的长度超过 20时 ,name 取前 20 个字符作为 name 的值 ; 如果…

【面试经典 150 | 二分查找】搜索旋转排序数组

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;二分查找 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行…

清理prometheus监控历史数据

# 18、清理prometheus&#xff08;监控&#xff09;历史数据 转至元数据起始 现象&#xff1a;1.监控大盘主机&#xff0c;/data磁盘使用率100% 2.开发者中心首页所有主机显示“未添加监控”&#xff1b; 思路&#xff1a;1.缩短prometheus的监控数据保存期限&#xff08;平…

宏集eX700M系列HMI实现港口设备数据上云

前言 随着港口设备信息化技术的快速发展&#xff0c;越来越多的企业想要把现场设备数据上传到云平台&#xff0c;进而实现关键数据的远程监控和分析处理。在此背景下&#xff0c;国内某信息化公司想要将港口设备数据通过MQTT上传到该公司自研IOT平台&#xff0c;实现数据上云&…

DDD学习

概述 学习一下DDD 什么是DDD DDD是领域驱动设计&#xff08;Domain Driven Design&#xff09;的缩写&#xff0c;是一种软件开发方法论。它强调将业务领域划分为多个紧凑的、自包含的领域&#xff0c;并通过强调领域模型的重要性来建立一个通用的语言和理解。 DDD鼓励开发…

js高级 笔记03

目录 01 如何避免全局变量 02 递归函数 03 浅拷贝 04 深拷贝 05 函数的调用模式 06 异步代码数据丢失问题 01 如何避免全局变量 自调用函数 常用于避免全局变量冲突的问题 不同的函数都有一个独立的作用域 所以可以解决命名冲突的问题 自调用函数也叫做沙箱函数 自调用函…

CSS all 属性

CSS all 属性 定义和使用 all 属性用于重置所有属性&#xff0c;除了 unicode-bidi 和 direction。 默认值:none继承:无动画:no。 阅读 animatable版本:CSS3JavaScript 语法:object.style.all“initial” 属性值 值描述initial修改所有元素属性或父元素的值为其初始化值in…

java项目的构建工具-Maven

黑马程序员JavaWeb开发教程 文章目录 一、概述1、介绍&#xff08;1&#xff09;介绍&#xff08;2&#xff09;Maven的作用&#xff08;3&#xff09;官网&#xff08;4&#xff09;仓库 2、安装 二、IDEA 集成 Maven1、配置Maven环境2、创建Maven项目&#xff08;1&#xff0…

入门必备:MySQL本地安装(Windows11)

下载安装 社区版下载地址:https://dev.mysql.com/downloads/ 选择合适自己操作系统的版本&#xff1a; 下载完成后是一个.msi文件&#xff0c;双击安装即可&#xff1b; 接下来请看图&#xff1a; 上面的步骤完成后&#xff0c;大概会弹出黑窗口并且有下面的UI界面&#xff…

Simlab python二次开发1-将所有缸套内表面半径加大1mm

Simlab python二次开发1-将所有缸套内表面半径加大1mm 1、打开模型文件2、getBodiesWithSubString&#xff08;&#xff09;从名字得到Bodies3、建Body类Group3.1、定义放入Group中的Bodies3.2、建Group 4、将缸套内表面建组&#xff0c;并扩半径1mm4.1、simlab.getBodiesFromG…

密码学 | 数字签名 + 数字证书

&#x1f951;原文&#xff1a;数字签名和数字证书的原理解读 - 知乎 &#x1f951;声明&#xff1a;后文图中若未明确指明&#xff0c;默认是 Bob 的公钥或私钥。 Step1&#xff1a;Bob 有两把钥匙&#xff0c;一把是公钥&#xff0c;另一把是私钥。 Step2&#xff1a;Bob 把…

基于Springboot+Vue的Java项目-企业客户管理系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

00_Linux

文章目录 LinuxLinux操作系统的组成Linux的文件系统Linux操作系统中的文件类型Linux操作系统的组织结构 Linux vs WindowsNAT vs 桥接模式 vs 仅主机Linux Shell命令Linux⽂件与⽬录管理相关指令目录文件普通文件文本编辑 用户管理添加用户删除用户用户组管理 文件权限管理权限…

[生活][杂项] 上班党的注意事项

前言 目前是上班已经接近两年了&#xff0c;目前的状态是&#xff0c;一个人租了一个单间在上班。对于这种情况有以下几点需要注意。 钥匙问题&#xff0c;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff…