You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Gateway OAuth2资源服务器权限配置与令牌转发问题

Spring Cloud Gateway OAuth2资源服务器配置与服务间令牌转发问题

一、配置网关的授权规则

因为网关基于WebFlux环境,你需要通过SecurityWebFilterChain Bean定义细粒度的授权规则,替换默认的全局认证逻辑,直接在配置类中编写路径匹配和权限校验即可:

@Configuration
@EnableWebFluxSecurity
public class GatewaySecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
            .authorizeExchange(exchanges -> exchanges
                // 开放无需授权的接口(比如健康检查、服务发现端点)
                .pathMatchers("/actuator/**", "/eureka/**").permitAll()
                // 对service1的接口要求用户拥有指定scope权限
                .pathMatchers("/api/service1/**").hasAuthority("SCOPE_default-user-scope")
                // 管理员接口要求对应权限
                .pathMatchers("/api/admin/**").hasAuthority("SCOPE_admin-scope")
                // 剩余所有请求必须经过认证
                .anyExchange().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.jwkSetUri("你的JWK集合地址"))
            );
        return http.build();
    }
}

注意:JWT中的scope字段会被自动转换为带SCOPE_前缀的权限,因此可以直接用hasAuthority做校验。如果需要更复杂的权限判断,也可以用access()方法结合自定义权限验证器实现。

二、后端服务间调用的令牌处理

分两种场景处理:

场景1:网关转发请求到后端服务

默认情况下,Spring Cloud Gateway会原样转发所有请求头,包括携带Bearer令牌的Authorization头。只要你的后端服务也配置成OAuth2资源服务器(和网关一样,引入spring-boot-starter-oauth2-resource-server依赖、配置JWK地址),就能直接接收并校验令牌,不需要额外做转发处理。

场景2:后端服务主动调用其他服务

如果是服务内部主动发起对其他服务的调用(比如服务A处理请求时主动调用服务B),需要手动将当前上下文的用户令牌传递过去,可以通过请求拦截器实现,用WebClient或RestTemplate都可以:

用WebClient实现(适配WebFlux服务)

@Bean
public WebClient webClient(ReactiveSecurityContextHolder reactiveSecurityContextHolder) {
    return WebClient.builder()
        .filter((request, next) -> {
            return reactiveSecurityContextHolder.getContext()
                .map(SecurityContext::getAuthentication)
                .cast(JwtAuthenticationToken.class)
                .map(tokenAuth -> tokenAuth.getToken().getTokenValue())
                .defaultIfEmpty("")
                .flatMap(token -> {
                    ClientRequest authorizedRequest = ClientRequest.from(request)
                        .header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
                        .build();
                    return next.exchange(authorizedRequest);
                });
        })
        .build();
}

用RestTemplate实现(适配Servlet服务)

@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getInterceptors().add((request, body, execution) -> {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth instanceof JwtAuthenticationToken) {
            String token = ((JwtAuthenticationToken) auth).getToken().getTokenValue();
            request.getHeaders().set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
        }
        return execution.execute(request, body);
    });
    return restTemplate;
}

后续服务间调用时,直接注入使用配置好的WebClient/RestTemplate,就能自动携带当前用户的Bearer令牌。

内容的提问来源于stack exchange,提问作者Dirk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:42:16