Spring Authorization Server如何限制客户端仅访问指定资源服务器?
可以实现这个需求,核心是通过配置客户端关联的资源服务器ID,并让资源服务器验证Token的受众(aud)字段来实现访问控制,具体步骤如下:
1. 在Authorization Server配置客户端关联资源服务器ID
修改你的RegisteredClientRepository配置,为每个客户端指定对应的资源服务器ID:
@Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient spa1 = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("client1") // 保留原有配置(授权类型、范围等) .redirectUri("http://127.0.0.1:3000/authorized") // 关联resourceServer1 .resourceId("resourceServer1") .build(); RegisteredClient spa2 = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("client2") // 保留原有配置 .redirectUri("http://127.0.0.1:3001/authorized") // 关联resourceServer2 .resourceId("resourceServer2") .build(); return new InMemoryRegisteredClientRepository(spa1, spa2); }
这里的.resourceId()方法对应你提到的旧版Spring Security中.resourceIds()的作用,配置后Authorization Server生成的Access Token会将该ID写入aud(受众)字段。
2. 配置资源服务器验证受众字段
每个资源服务器需要配置自身的资源ID,并验证Token的aud字段是否匹配,只有匹配的Token才能访问该资源服务器的端点。
方式一:基于@EnableResourceServer的传统配置
@Configuration @EnableResourceServer public class ResourceServer1Config extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { // 指定当前资源服务器的ID,与客户端配置的resourceId对应 resources.resourceId("resourceServer1"); } @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated(); } }
同理,ResourceServer2Config只需将resourceId改为"resourceServer2"即可。
方式二:基于Spring Security 5+的OAuth2资源服务器新配置
如果使用较新版本的Spring Security,推荐使用这种方式:
@Configuration public class ResourceServer1Config { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .audienceValidator(audienceValidator()) ) ) .authorizeRequests(auth -> auth .anyRequest().authenticated() ); return http.build(); } private OAuth2TokenValidator<Jwt> audienceValidator() { // 验证Token的aud字段是否包含当前资源服务器ID OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator("resourceServer1"); return new DelegatingOAuth2TokenValidator<>(JwtValidators.createDefault(), audienceValidator); } static class AudienceValidator implements OAuth2TokenValidator<Jwt> { private final String targetAudience; AudienceValidator(String targetAudience) { this.targetAudience = targetAudience; } @Override public OAuth2TokenValidatorResult validate(Jwt token) { if (token.getAudience().contains(targetAudience)) { return OAuth2TokenValidatorResult.success(); } return OAuth2TokenValidatorResult.failure( new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, "Token受众不匹配当前资源服务器", null) ); } } }
原理说明
- 客户端配置
resourceId后,Authorization Server生成的Access Token会将该ID加入aud字段; - 资源服务器通过验证Token的
aud字段是否包含自身的资源ID,实现对客户端访问权限的限制:只有关联了该资源ID的客户端生成的Token,才能通过验证并访问资源端点。
内容的提问来源于stack exchange,提问作者george
相关产品推荐
相关产品推荐

