如何实现基于OAuth2授权码模式的BFF授权头转发?
核心逻辑
BFF作为资源服务器接收客户端携带Authorization: Bearer <token>的请求,验证Token合法性后,将该请求头原样转发给所有下游Feign调用的资源服务;下游服务同样作为资源服务器验证Token后返回数据,BFF聚合响应后返回给客户端。
方案一:Feign请求拦截器(推荐)
通过自定义Feign拦截器,从当前请求上下文提取Authorization头,注入到Feign请求中。
1. BFF资源服务器配置
配置BFF作为OAuth2资源服务器,验证客户端传入的Token:
@Configuration @EnableResourceServer public class BffResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(); // 若使用不透明Token,可替换为opaqueToken() } }
2. 自定义Feign拦截器
实现RequestInterceptor,从请求上下文提取Authorization头并添加到Feign请求:
@Component public class AuthorizationHeaderFeignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); if (authHeader != null) { template.header(HttpHeaders.AUTHORIZATION, authHeader); } } } }
3. Feign客户端定义
正常定义Feign客户端,拦截器会自动生效:
@FeignClient(name = "downstream-service") public interface DownstreamServiceClient { @GetMapping("/api/data") ResponseEntity<String> fetchData(); }
4. BFF控制器示例
@RestController @RequestMapping("/bff/api") public class BffController { private final DownstreamServiceClient downstreamClient; public BffController(DownstreamServiceClient downstreamClient) { this.downstreamClient = downstreamClient; } @GetMapping("/aggregate") public ResponseEntity<String> getAggregatedData() { // 调用下游服务时,Authorization头已自动转发 ResponseEntity<String> downstreamResp = downstreamClient.fetchData(); // 此处可添加响应聚合逻辑 return ResponseEntity.ok("Aggregated result: " + downstreamResp.getBody()); } }
5. 下游资源服务配置
下游服务同样配置为资源服务器,验证Token:
@Configuration @EnableResourceServer public class DownstreamResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(); } }
方案二:Spring Cloud Gateway作为BFF
若使用Gateway作为BFF,通过自定义全局过滤器转发Authorization头:
全局过滤器实现
@Component public class AuthHeaderForwardFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String authHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION); if (authHeader != null) { ServerHttpRequest modifiedRequest = exchange.getRequest().mutate() .header(HttpHeaders.AUTHORIZATION, authHeader) .build(); return chain.filter(exchange.mutate().request(modifiedRequest).build()); } return chain.filter(exchange); } @Override public int getOrder() { return -100; // 确保过滤器在前置逻辑前执行 } }
Gateway路由配置(YAML)
spring: cloud: gateway: routes: - id: downstream-service-route uri: lb://downstream-service predicates: - Path=/bff/api/downstream/** filters: - StripPrefix=2 # 移除/bff/api前缀,转发到下游的/api路径
注意事项
- 确保BFF和下游服务对接同一OAuth2授权服务器,保证Token验证规则一致
- 可添加Token有效性二次校验(如调用授权服务器的introspect接口),避免转发无效Token
- 若使用JWT,下游服务可本地验证签名,无需调用授权服务器,性能更优
- 如需更复杂的Token中继(如交换为下游专用Token),可使用Spring Security OAuth2的
TokenExchangeFilterFunction
内容的提问来源于stack exchange,提问作者BUKTOP
相关产品推荐
相关产品推荐

