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

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

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.dtcms.com/a/268559.html

相关文章:

  • window 服务器上部署前端静态资源以及nginx 配置
  • 揭秘图像LLM:从像素到语言的智能转换
  • 创意Python爱心代码
  • 基于Flink 1.20、StarRocks与TiCDC构建高效数据处理链路教程
  • linux如何下载github的一个项目
  • stm32与tp-linkv2接线、解决识别不到芯片问题
  • C++ -- string类的模拟实现
  • Go的标准库http原理解析
  • 【论文阅读】Few-Shot PPG Signal Generation via Guided Diffusion Models
  • Web Worker:让前端飞起来的隐形引擎
  • 第0章:开篇词 - 嘿,别怕,AI应用开发没那么神!
  • 【PaddleOCR】数据合成工具 Style-Text安装与使用案例介绍
  • 【机器学习笔记 Ⅲ】3 异常检测算法
  • 4D-VLA:具有跨场景标定的时空视觉-语言-动作预训练
  • Linux运维安全新范式:基于TCPIP与SSH密钥的无密码认证实战
  • 【保姆级图文详解】探秘 Prompt 工程:AI 交互的关键密码
  • C++多线程网络编程:助力高并发服务器性能提升
  • 无人机精准降落辅助系统核心技术解析
  • 一文讲清楚React Fiber
  • RAG 相关概念学习
  • VMware 17.0.2-21581411 安装教程(附详细步骤+序列号激活指南)
  • 【牛客算法】 小红的奇偶抽取
  • kotlin+MongoTemplate的时间类型为is_date类型 pymongo如何处理
  • 【vue】用conda配置nodejs,一键开通模版使用权
  • 设计模式分析
  • 1.1_5_1 计算机网络的性能指标(上)
  • 大模型在肾囊肿诊疗全流程预测及应用研究报告
  • kafka总结
  • 【Java编程动手学】Java常用工具类
  • Apache Cloudberry 亮相 2025 IvorySQL 生态大会暨 PostgreSQL 高峰论坛