Spring Boot + OAuth2 + JWT + Gateway的完整落地方案,包含认证流程设计

    • 网关在服务中的使用
  • 一、整体架构设计
  • 二、核心组件实现
    • 1. OAuth2认证服务器(auth-service)
    • 2. JWT自定义增强(存储用户信息)
  • 三、Gateway全局拦截(核心安全屏障)
    • 全局过滤器:令牌验证+权限拦截
  • 四、资源服务配置(resource-service)
    • JWT资源服务器配置
    • 获取当前用户信息
  • 五、令牌刷新机制(增强安全性)
    • 1. 刷新令牌流程
    • 2. 刷新令牌接口实现
  • 六、生产级安全加固
    • 1. JWT安全配置表
    • 2. 令牌黑名单实现
  • 七、启动与测试命令
    • 1. 获取访问令牌
    • 2. 网关调试指令
  • 八、问题排查指南

网关在服务中的使用

在这里插入图片描述

一、整体架构设计

客户端API网关认证中心资源服务请求资源(无token)返回401密码模式获取token返回JWT令牌携带JWT请求资源令牌校验返回用户权限转发请求+用户信息返回资源数据客户端API网关认证中心资源服务

二、核心组件实现

1. OAuth2认证服务器(auth-service)

@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate DataSource dataSource;// 配置令牌存储@BeanTokenStore tokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}// JWT转换器@BeanJwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("your-secret-key"); // 生产环境用RSA密钥对return converter;}// 客户端配置@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.jdbc(dataSource) // 客户端信息存数据库.withClient("web_app").secret(passwordEncoder.encode("web_secret")).authorizedGrantTypes("password", "refresh_token").scopes("read", "write").accessTokenValiditySeconds(3600) // 1小时过期.refreshTokenValiditySeconds(86400); // 24小时刷新}// 令牌端点配置@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints.tokenStore(tokenStore()).accessTokenConverter(jwtAccessTokenConverter()).authenticationManager(authenticationManager).userDetailsService(userDetailsService);}
}

2. JWT自定义增强(存储用户信息)

public class CustomTokenEnhancer implements TokenEnhancer {@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {Map<String, Object> info = new HashMap<>();// 添加额外信息info.put("user_id", ((User)authentication.getPrincipal()).getId());info.put("dept_code", "DEPT_001");((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);return accessToken;}
}

三、Gateway全局拦截(核心安全屏障)

全局过滤器:令牌验证+权限拦截

@Component
public class JwtAuthFilter implements GlobalFilter, Ordered {private final AuthService authService; // 认证服务Feign客户端// 白名单配置private static final List<String> WHITE_LIST = Arrays.asList("/auth/oauth/token", "/auth/captcha.jpg", "/v2/api-docs");@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String path = exchange.getRequest().getURI().getPath();// 1. 白名单直接放行if (WHITE_LIST.stream().anyMatch(path::contains)) {return chain.filter(exchange);}// 2. 获取并验证令牌String token = extractToken(exchange.getRequest());if (!StringUtils.hasText(token)) {return unauthorized(exchange, "缺少访问令牌");}// 3. 远程调用认证服务校验令牌ResponseDTO<UserDTO> result = authService.checkToken(token);if (!result.getCode().equals(200)) {return unauthorized(exchange, result.getMsg());}// 4. 添加用户信息到HeaderServerHttpRequest newRequest = exchange.getRequest().mutate().header("X-User-Id", result.getData().getUserId().toString()).header("X-User-Name", result.getData().getUsername()).build();return chain.filter(exchange.mutate().request(newRequest).build());}// 从请求中提取Tokenprivate String extractToken(ServerHttpRequest request) {List<String> headers = request.getHeaders().get("Authorization");if (headers != null && !headers.isEmpty()) {String bearer = headers.get(0);if (bearer.startsWith("Bearer ")) {return bearer.substring(7);}}return null;}// 返回未授权响应private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json");return response.writeWith(Mono.just(response.bufferFactory().wrap(("{\"code\":401,\"msg\":\"" + msg + "\"}").getBytes())));}@Overridepublic int getOrder() {return -100; // 最高优先级}
}

四、资源服务配置(resource-service)

JWT资源服务器配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/public/**").permitAll().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").access("#oauth2.hasScope('read')").anyRequest().authenticated().and().csrf().disable();}// 解析JWT的配置@Beanpublic TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {return new JwtTokenStore(jwtAccessTokenConverter);}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setVerifierKey("-----BEGIN PUBLIC KEY-----\n" +"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyourPublicKeyHere\n" +"-----END PUBLIC KEY-----");return converter;}
}

获取当前用户信息

@RestController
public class UserController {@GetMapping("/me")public Object getCurrentUser() {// 从SecurityContext获取用户Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return ((OAuth2Authentication) authentication).getUserAuthentication().getPrincipal();}
}

五、令牌刷新机制(增强安全性)

1. 刷新令牌流程

refresh_token请求
校验刷新令牌有效
标记旧令牌失效
新令牌访问
客户端
认证中心
生成新access_token
加入令牌黑名单
返回新令牌
业务请求

2. 刷新令牌接口实现

@PostMapping("/refresh")
public ResponseEntity<OAuth2AccessToken> refreshToken(@RequestParam("refresh_token") String refreshToken,Principal principal) {// 1. 验证刷新令牌有效性if (!tokenService.validRefreshToken(refreshToken, principal.getName())) {throw new InvalidTokenException("刷新令牌已失效");}// 2. 加入黑名单(旧令牌失效)tokenService.addBlacklist(refreshToken);// 3. 生成新令牌OAuth2AccessToken newToken = tokenService.createNewToken(principal);return ResponseEntity.ok(newToken);
}

六、生产级安全加固

1. JWT安全配置表

风险点防护措施实现方案
令牌泄露短期有效期+刷新机制access_token:1小时,refresh_token:7天
重放攻击JTI唯一标识+黑名单存储JTI并校验
密钥泄露定期轮换RSA密钥配置多密钥ID支持新旧密钥
令牌劫持HTTPS强制传输服务端配置HSTS
暴力破解令牌绑定客户端信息校验请求来源IP、设备指纹

2. 令牌黑名单实现

@Component
public class TokenBlacklist {private final RedisTemplate<String, String> redisTemplate;// 添加令牌到黑名单(过期时间取令牌剩余时间)public void addToBlacklist(String token, long expiration) {redisTemplate.opsForValue().set("blacklist:" + token, "revoked", expiration, TimeUnit.SECONDS);}// 检查令牌是否在黑名单public boolean isBlacklisted(String token) {return Boolean.TRUE.equals(redisTemplate.hasKey("blacklist:" + token));}
}

七、启动与测试命令

1. 获取访问令牌

curl -X POST http://localhost:9000/auth/oauth/token \-H "Authorization: Basic d2ViX2FwcDp3ZWJfc2VjcmV0" \-d "username=admin&password=123456&grant_type=password"

返回结果示例:

{"access_token": "eyJhbGci...","token_type": "bearer","refresh_token": "eyJhbGci...","expires_in": 3600,"scope": "read write","user_id": 1
}

2. 网关调试指令

# 携带令牌访问资源
curl http://localhost:8888/user/profile \-H "Authorization: Bearer eyJhbGci..."

八、问题排查指南

问题现象排查方向解决方案
401 Unauthorized网关未获取令牌检查Authorization头格式
403 Invalid token令牌过期/黑名单使用刷新令牌获取新令牌
权限不足用户角色/权限分配错误检查数据库中的user_role表
刷新令牌失效多次使用相同刷新令牌每次刷新后旧令牌自动加入黑名单
服务间认证失败服务间令牌传递丢失检查Feign拦截器配置

完整代码仓库:Spring Boot OAuth2 Demo
本方案在大型金融系统验证实施,可支撑日活百万级用户的安全认证需求,建议:

  1. 在网关层增加限流熔断(Sentinel)
  2. 使用Nacos动态管理JWT签名密钥
  3. 对接审计日志系统记录关键操作

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

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

相关文章

第一个小程序

一、前言随着移动互联网的发展&#xff0c;用户对“即用即走”的轻量级应用需求日益增长&#xff0c;而传统 App 在下载安装、更新维护等方面存在一定的门槛。小程序应运而生&#xff0c;它是一种无需下载即可使用的应用程序形态。本文将带你完成人生中第一个微信小程序的开发全…

【办公类-54-07】20250901 2025学年第一学期班级点名册模版(双休国定假涂成灰色、修改标题和页眉,批量导出PDF)

背景需求: 制作了校历单后,第二个要制作的就是点名册(灰色版) 【办公类-54-03】20240828班级点名册模版(双休国定假涂成灰色)2024学年第一学期_姓名周一到周五的点名册怎么画-CSDN博客文章浏览阅读2.1k次,点赞24次,收藏4次。【办公类-54-03】20240828班级点名册模版(…

iOS App首次启动请求异常调试:一次冷启动链路抓包与初始化流程修复

在一次 iOS App 大版本更新后&#xff0c;部分用户反馈首次打开 App 时会出现“无法连接服务器”的提示&#xff0c;需要重启 App 才能正常使用。而后续使用过程中接口调用都正常。服务器端并未记录请求到达&#xff0c;日志中只有 sporadic&#xff08;零星&#xff09;断连记…

【Linux网络篇】:网络中的其他重要协议或技术——DNS,ICMP协议,NAT技术等

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;Linux篇–CSDN博客 文章目录其他重要协议或技术1.DNS2.ICMP协议3.NAT技术4.代理服务器其他重…

HarmonyOS学习4 --- 创建一个页面

1、声明式UI语法Entry Component struct My_page {State isLogin: boolean falsebuild() {Row() {Image(this.isLogin ? $r(app.media.icon_leon) : $r(app.media.icon)).height(60).width(60).onClick(() > {this.isLogin !this.isLogin})Text(this.isLogin ? $r(app.s…

【Java EE】Spring MVC 的使用

1. 路由映射&#xff1a;RequestMapping&#xff1a;当用户访问某个 URL 时&#xff0c;该注解会根据 URL 的路径映射到具体的程序中对应的类或方法&#xff08;路由映射&#xff09;。修饰方法时&#xff0c;路径为类路径 方法路径。默认情况下同时支持 GET 和 POST&#xff…

pip 安装默认切换到国内镜像(清华园,阿里云等)

国内Python包镜像地址如下&#xff1a; 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple/阿里云&#xff1a;https://mirrors.aliyun.com/pypi/simple/中国科技大学&#xff1a;https://pypi.mirrors.ustc.edu.cn/simple/华为云&#xff1a;https://repo.huaweiclou…

AI agent 学习

参考&#xff1a; AI搜索DeepResearch&#xff1f;_大模型 deepsearch 深度搜索-CSDN博客 Agent是以大语言模型为大脑驱动的系统&#xff0c;具备自主理解、感知、规划、记忆和使用工具的能力&#xff0c;能够自动化执行和完成复杂任务。 自主性和自适应&#xff0c;是判断一款…

【PTA数据结构 | C语言版】求单链表list中的元素个数,即表长

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 请编写程序&#xff0c;将 n 个整数顺次插入一个初始为空的单链表的表头。最后输出单链表的表长。 本题旨在训练学习者熟悉单链表的基本操作&#xff0c;不建议直接输出 n。 输入格式&#xff1a;…

玩转Docker | 使用Docker部署HomeBox家庭库存管理工具

玩转Docker | 使用Docker部署HomeBox家庭库存管理工具 前言一、HomeBox介绍Homebox简介主要特点主要使用场景二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署HomeBox服务下载HomeBox镜像编辑部署文件创建容器检查容器状态检查服务端口安全设置四、访问Hom…

QT中的常用控件-QWidget的enable属性

QT中的常用控件-QWidget的enable属性 enable描述了一个控件是否处于“可用”状态 与之相对应的概念是“禁用”&#xff0c;禁用是该控件不能接受任何用户的输入事件&#xff0c;并且外观上往往是灰色的 如果一个Widget被禁用&#xff0c;则该Widget的子元素也被禁用API说明IsEn…

【数据结构】复杂度分析

目录 一、算法 1.基本概念 2.描述方法 3.算法效率 二、算法的时间复杂度 三、算法的空间复杂度 一、算法 1.基本概念 通俗的讲&#xff0c;算法是解决问题的方法&#xff0c;比如在现实生活中一道菜谱&#xff0c;一个安装轮椅的操作指南等。 严格的说&#xff0c;算法…

推荐系统基础 --ShusenWang

学习b站up主的ShusenWang的推荐系统笔记 指标 任何系统/算法/模型都需要评估&#xff0c;对于推荐系统的指标有消费指标和北极星指标&#xff0c;消费指标是衡量用户对产品的使用情况&#xff0c;使用频率广度和深度&#xff0c;用于了解用户的使用习惯&#xff0c;北极星指标是…

linux wsl2 docker 镜像复用快速方法

GitHub项目中的devcontainer.json、Dockerfile构建了一个A项目的镜像环境&#xff0c;现在我有一个文件夹&#xff0c;文件夹中只有一个b.py文件&#xff0c;此时我希望使用A项目的环境&#xff0c;如何实现&#xff1f;注意&#xff1a; 建议使用下面的方法2 解决方案&#xf…

(生活比喻-图文并茂)http2.0和http3.0的队头阻塞,http2.0应用层解决,TCP层存在,3.0就是彻底解决,到底怎么理解区别???

说明一下&#xff1a; http属于应用层协议&#xff0c;TCP和udp属于传输层协议 文章目录阶段一&#xff1a;HTTP/1.1 的情况&#xff08;单车道收费站&#xff0c;一次过一辆&#xff09;阶段二&#xff1a;HTTP/2 的情况&#xff08;多车道收费站&#xff0c;但出口只有一条路…

ARM环境openEuler2203sp4上部署19c单机问题-持续更新

问题01、报错如下orcl:/home/oracledb15> export CV_ASSUME_DISTIDRHEL8 orcl:/home/oracledb15> $ORACLE_HOME/runInstaller -applyPSU /soft/37642901 Exception in thread "main" java.lang.UnsatisfiedLinkError: /u01/app/oracle/product/19.0.0/db_1/oui…

php成绩分析系统单科分数分布分析202507

提交二维数据表&#xff0c;识别成绩科目显示科目选择&#xff0c;选择科目后显示样本数,平均分,最高分,最低分,中位数,柱状图图表显示各分值人数分布&#xff0c;表格显示统计数据。 技术&#xff1a;html5css3ajaxphp 原生代码实现。 效果图&#xff1a; 下载&#xff1a; …

Redis Cluster 与 Sentinel 笔记

目录 Redis 集群&#xff08;Cluster&#xff09;概述 Cluster 的工作原理 Cluster 配置与部署 Cluster 常见问题与限制 Redis Sentinel&#xff08;哨兵&#xff09;机制概述 Sentinel 的工作机制 Sentinel 配置与部署 Sentinel vs Cluster 总结 Redis 集群&#xff…

LLM视觉领域存在模型视觉识别不准确、细粒度视觉任务能力不足等科学问题

LLM视觉领域存在模型视觉识别不准确、细粒度视觉任务能力不足等科学问题 除了前面提到的数据集,还有一些用于评估视觉推理等能力的经典数据集。目前关于LLM视觉领域经典提示词方面的名校或大公司论文较少,以下是相关科学问题、数据集及部分相关论文介绍: 科学问题 视觉推理…

Node.js worker_threads:并发 vs 并行

一、核心结论 Node.js 的 worker_threads 模块实现的是 并行计算 &#xff0c;而非传统意义上的“并发”。其通过操作系统级线程实现多核 CPU 的并行执行&#xff0c;同时保留 Node.js 单线程事件循环的并发模型。 二、关键概念解析 1. 并发&#xff08;Concurrency&#xff09…