您现在的位置是:亿华云 > 知识
SpringCloud微服务中网关如何传递用户信息?
亿华云2025-10-04 03:41:32【知识】3人已围观
简介来源:JAVA日知录大家好,我是飘渺。今天来解决一个粉丝的问题:在SpringCloud Gateway实现鉴权时,如何在转发请求到子业务模块时获取登录用户信息?在上一篇文章中,我们已经实现了在网关层
来源:JAVA日知录
大家好,服务我是中网飘渺。
今天来解决一个粉丝的关何问题:在SpringCloud Gateway实现鉴权时,如何在转发请求到子业务模块时获取登录用户信息?传递

在上一篇文章中,我们已经实现了在网关层进行身份认证:首先从请求头中获取 Authorization 参数得到 JWT Token,用户然后解开 JWT 后即可获取用户信息。信息
以下是服务相关代码:
@Overridepublic AuthenticatorResult auth(ServerWebExchange exchange){
ServerHttpRequest request = exchange.getRequest();
HttpHeaders httpHeaders = request.getHeaders();
// 获取JWT请求头 AuthorizationString token = httpHeaders.getFirst(HttpHeaders.AUTHORIZATION);
if(Objects.nonNull(token)) {
try{
String subjectFromJWT = JwtUtil.getSubjectFromJWT(token);
log.info("用户请求token: { } , 身份Subject:{ }", token, subjectFromJWT);
return new AuthenticatorResult(true, "认证通过");
} catch(ParseException | JOSEException e) {
log.error("token解析失败{ }",token);
return new AuthenticatorResult(false, "Token错误,请重新登录!");
}
}
return new AuthenticatorResult(false, "Token为空,请重新登录!");
}
实现方案
通常情况下,在 Spring Cloud 中将用户信息透传给后端服务有两种方式:
第一种:在网关解析出用户的中网 Token 得到用户 ID,然后将用户 ID 添加到请求头中传递下去。关何
第二种:在网关直接把 Token 传递下去,传递由各个子服务自行解析。用户
在 DailyMart 中我推荐使用第一种方式,信息将 JWT Token 解析后直接透传给后端服务。服务
以下是中网实现方案:
在网关解析 JWT Token 后得到 UserID,修改 Spring Cloud Gateway 的关何请求头,将 UserID 添加到请求头中。自定义用户上下文 UserContextHolder,站群服务器并使用 ThreadLocal 进行存储。在微服务中的 Web 组件中创建拦截器 UserTokenInterceptor,从 Request 中获取 UserID,并将其添加到用户上下文 UserContextHolder 中。将拦截器 UserInterceptor 注册到 Spring 容器中。代码实现
1、在SpringCloud Gateway中修改请求头
public class DefaultApiAuthenticator implements ApiAuthenticator{
@Override public AuthenticatorResult auth(ServerWebExchange exchange){
...
if(Objects.nonNull(token)) {
try{
String subjectFromJWT = JwtUtil.getSubjectFromJWT(token);
//重新设置请求头mutateNewHeader(exchange, subjectFromJWT);
return new AuthenticatorResult(true, "认证通过");
} catch(ParseException | JOSEException e) {
log.error("token解析失败");
return new AuthenticatorResult(false, "Token错误,请重新登录!");
}
}
return new AuthenticatorResult(false, "Token为空,请重新登录!");
}
/
*** 重新构建请求头,将用户账号放入Token
* @paramsubject 用户身份
*/ private void mutateNewHeader(ServerWebExchange exchange, String subject){
ServerHttpRequest newRequest = exchange.getRequest().mutate().header(CommonConstant.X_CLIENT_TOKEN, subject).build();
exchange.mutate().request(newRequest).build();
}
}
2、自定义用户上下文UserContextHolder
public class UserContextHolder{
private final ThreadLocal
{
this.threadLocal = newThreadLocal<>();
}
public static UserContextHolder getInstance(){
returnSingletonHolder.instance;
}
/
*** 设置用户数据
* @paramuserId 用户账号
*/ public void setCurrentUser(String userId){
this.threadLocal.set(userId);
}
/
*** 获取当前用户
* @returnuserId
*/ public String getCurrentUser(){
return this.threadLocal.get();
}
/
*** 清理用户信息
*/ public void clear(){
this.threadLocal.remove();
}
}
3、创建自定义拦截器UserTokenInterceptor
由于每个服务中都需要用到此功能,所以我们将此功能在公共组件dailymart-web-spring-boot-starter中实现。
public class UserTokenInterceptor implements HandlerInterceptor{
@Override public boolean preHandle(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception{
String userId = request.getHeader(CommonConstant.X_CLIENT_TOKEN);
// 设置用户信息UserContextHolder.getInstance().setCurrentUser(userId);
return true;
}
@Override public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) throws Exception{
UserContextHolder.getInstance().clear();
}
}
这里先从请求头中获取userId,然后使用单例类UserContextHolder将userId添加到ThreadLocal中,当然在处理完成后需要清空ThreadLocal的值,不然会出现内存泄露。
4、创建配置类,在Spring中注册拦截器
@SpringBootConfiguration@ConditionalOnWebApplicationpublic class WebMvcConfigurerAdaptor implements WebMvcConfigurer{
@Override public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(userInterceptor())
.addPathPatterns("/api/pd/**")
.excludePathPatterns(excludePathList);
}
private final String[] excludePathList = newString[]{
"/api/pd/customer/login"};
@Bean public HandlerInterceptor userInterceptor(){
return newUserTokenInterceptor();
}
}
在上篇文章中我们已经规定来源标识为/pd的才算是浏览器的请求,云服务器提供商所以在这个拦截器中我们只需要配置特定的拦截地址即可。
5、获取userId
在后续微服务中如果需要获取 UserID,只需从 UserContextHolder 获取即可:
@Operation(summary = "用户测试接口")
@PostMapping("/api/pd/customer/info")
public void info(){
String currentUser = UserContextHolder.getInstance().getCurrentUser();
log.info("当前登录用户:"+ currentUser);
}
小结
本文介绍了在 Spring Cloud Gateway 中实现鉴权并将用户信息传递给后端服务的解决方案。通过解析 JWT Token 并将用户身份信息添加到请求头,实现了简单而有效的用户身份认证和信息传递。当然,文章中仅仅传递了UserID,在实际使用中,大家也可以先在网关层通过UserID获取用户的详细信息,再将详细信息进行传递。同时,本文涉及的代码都已经上传至Github,感兴趣的可以通过文末方式获取。
很赞哦!(59223)
相关文章
- 什么是im域名?新手需要了解im域名哪些?
- 克服网络障碍:Prometheus如何通过间接方式采集目标服务数据
- 浪潮信息联合英特尔全球首发全液冷冷板参考设计,打通液冷规模化应用最后一公里
- Arm Neoverse CSS V3 助力云计算实现 TCO 优化的机密计算
- Status、Creation Date、Expiration Date
- X86与ARM技术对比:一场芯片领域的深度较量
- 数据中心越建越大,怎么办?
- MediaTek携手生态伙伴联合发布《生成式AI手机产业白皮书》,共同定义生成式AI手机
- 为了避免将来给我们的个人站长带来的麻烦,在选择域名后缀时,我们的站长最好省略不稳定的后缀域名,比如n,因为我们不知道策略什么时候会改变,更不用说我们将来是否还能控制这个域名了。因此,如果站长不是企业,或者有选择的话,如果不能选择域名的cn类,最好不要选择它。
- 英特尔以现代软件工具实现AI性能提升,让AI无处不在