Spring Security 5下同OAuth2授权服务器的两资源服务客户端模式调用方案咨询
Spring Security 5+ 客户端凭证模式跨资源服务调用实现方案
1. 引入核心依赖
需在发起调用的服务中引入OAuth2客户端启动器,Maven依赖示例如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. 配置OAuth2客户端参数
在application.yml中添加授权服务器、客户端凭证相关配置:
spring: security: oauth2: client: registration: # 自定义客户端注册ID,后续配置会用到 target-service-client: client-id: 你的客户端ID client-secret: 你的客户端密钥 authorization-grant-type: client_credentials # 填目标资源服务要求的scope scope: target-service:read,target-service:write provider: target-service-client: # 授权服务器的令牌颁发接口地址 token-uri: http://你的授权服务器地址/oauth2/token
3. 配置带自动令牌注入的RestTemplate
Spring Security 5已原生提供客户端凭证模式的令牌自动管理能力,无需手动调用/oauth2/token接口获取令牌,直接配置拦截器即可:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.*; import org.springframework.security.oauth2.client.http.OAuth2ClientHttpRequestInterceptor; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.web.client.RestTemplate; import java.util.Collections; @Configuration public class OAuth2RestConfig { @Bean public OAuth2AuthorizedClientManager clientCredentialsAuthorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { // 仅启用客户端凭证模式的令牌提供者 OAuth2AuthorizedClientProvider provider = OAuth2AuthorizedClientProviderBuilder .builder() .clientCredentials() .build(); DefaultOAuth2AuthorizedClientManager manager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository ); manager.setAuthorizedClientProvider(provider); return manager; } @Bean public RestTemplate oauth2ClientRestTemplate(OAuth2AuthorizedClientManager manager) { RestTemplate restTemplate = new RestTemplate(); // 添加OAuth2请求拦截器,自动处理令牌获取、缓存、刷新、请求头注入 OAuth2ClientHttpRequestInterceptor interceptor = new OAuth2ClientHttpRequestInterceptor(manager); restTemplate.setInterceptors(Collections.singletonList(interceptor)); return restTemplate; } }
4. 调用目标服务受保护接口
直接注入上述配置的oauth2ClientRestTemplate发起调用即可,框架会自动处理令牌相关逻辑:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class TargetServiceCaller { @Autowired @Qualifier("oauth2ClientRestTemplate") private RestTemplate oauth2RestTemplate; public String getProtectedResource() { // 目标资源服务的受保护接口地址 String endpoint = "http://目标资源服务地址/protected/api"; return oauth2RestTemplate.getForObject(endpoint, String.class); } }
常见失败原因排查
- 客户端注册时未开通
client_credentials授权模式,导致令牌请求被授权服务器拒绝 - 配置的
scope未包含目标资源服务要求的权限范围,拿到的令牌访问资源时返回403 - 手动调用令牌接口时
Authorization请求头格式错误,正确格式为Bearer 令牌值(Bearer和令牌中间需加空格) - 授权服务器要求令牌的
aud(受众)字段包含目标资源服务标识,需在客户端注册时配置对应受众参数
内容的提问来源于stack exchange,提问作者Introvert
相关产品推荐
相关产品推荐

