通过FeignClient路由至Spring Cloud API Gateway实现JWT授权问题
问题分析
你的Feign调用之所以未生效,核心原因是Feign默认不会自动传递当前请求的Authorization头(即JWT Token),导致网关的AuthorizationHeaderFilter拿不到Token,验证不通过,请求被拦截。
解决方案
下面提供两种可行的实现方式,让Feign调用携带JWT Token经过网关验证:
方式一:手动传递Authorization头
直接在Feign接口方法中添加@RequestHeader参数,调用时从当前请求中获取Token传入:
1. 修改Feign接口
@FeignClient(name = "RATING-SERVICE", url="http://localhost:9000") public interface RatingService { @GetMapping("/ratingsdata/{managerInput}/{peerInput}/{dept}") Double getRating( @RequestHeader("Authorization") String authorizationHeader, @PathVariable Double managerInput, @PathVariable Double peerInput, @PathVariable String dept); }
2. 在调用处传入Token
@Autowired private RatingService ratingService; @Autowired private HttpServletRequest request; // 从当前请求中获取Authorization头,传入Feign调用 Double empRating = ratingService.getRating( request.getHeader("Authorization"), employee.getManagerPoints(), employee.getPeersPoints(), employee.getDepartment().getDeptName());
方式二:全局自动传递Token(推荐)
实现Feign的RequestInterceptor,自动从当前请求上下文提取Authorization头并添加到Feign请求中,无需手动传递:
1. 创建Feign请求拦截器
import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Component public class FeignAuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); String authorization = request.getHeader("Authorization"); if (authorization != null) { template.header("Authorization", authorization); } } } }
2. 简化Feign接口
拦截器生效后,Feign接口无需额外参数,保持原有写法即可:
@FeignClient(name = "RATING-SERVICE", url="http://localhost:9000") public interface RatingService { @GetMapping("/ratingsdata/{managerInput}/{peerInput}/{dept}") Double getRating(@PathVariable Double managerInput, @PathVariable Double peerInput, @PathVariable String dept); }
额外优化建议
- 避免硬编码网关地址:可以将网关注册到Eureka,Feign直接调用网关的服务名
API-GATEWAY,替换硬编码的url="http://localhost:9000",提升架构灵活性:@FeignClient(name = "API-GATEWAY") public interface RatingService { // ... 方法不变 } - 异步场景处理:如果是异步调用,需要手动传递请求上下文,否则
RequestContextHolder会无法获取到当前请求,导致Token无法传递。
内容的提问来源于stack exchange,提问作者Ambrish Mayank
相关产品推荐
相关产品推荐

