我有一个Oauth 2客户端它实际上与另一个充当授权服务器(auth-server)的微服务交互。我有一个端点(使用spring mvc)。它有注释
@PreAuthorize("has Scope(T(.........).
@Configuration
public class AuthWebClientConfiguration {
@Bean
public OAuth2AuthorizedClientManager authorizedManager(
ClientRegistrationRepository client,
OAuth2AuthorizedClientRepository authorizedClient
) {
OAuth2AuthorizedClientProvider authorizedProvider =
OAuth2AuthorizedClientProviderBuilder
.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedManager =
new DefaultOAuth2AuthorizedClientManager(
client,
authorizedClient
);
authorizedClientManager.setAuthorizedClientProvider(authorizedProvider);
return authorizedManager;
}
@Bean
public ServletOAuth2AuthorizedClientExchangeFilterFunction oauthClient(OAuth2AuthorizedClientManager authorizedManager) {
return new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedManager);
}
}
@Service
@RequiredArgsConstructor
public class AuthClientManager {
public static final String SERVICE_ID = "my-service";
private final OAuth2AuthorizedClientManager oAuth2Manager;
private final ServletOAuth2AuthorizedClientExchangeFilterFunction
filterFunction;
private final WebClient webClient;
private WebClient client;
public WebClient getClient() {
return Optional.ofNullable(client)
.orElseGet(() -> {
OAuth2AuthorizeRequest authorizeRequest =
OAuth2AuthorizeRequest.withClientRegistrationId(SERVICE_ID)
.principal(SERVICE_ID)
.build();
client = webClient
.mutate()
.filter(
(request, next) -> next
.exchange(
ClientRequest.from(request)
.attributes(
oauth2AuthorizedClient(
oAuth2Manager.authorize(authorizeRequest)
)
).build()
)
)
.apply(filterFunction.oauth2Configuration())
.build();
return client;
});
}
}
<<ul>@RequestMapping("email")
public interface RestController {
@PreAuthorize("hasScope(T(......MESSAGE_SEND)")
@PostMapping("v1/message")
ResponseEntity<Void> send(@Valid @RequestBody Dto dto);
}
- 端点的实现
@RestController
@RequiredArgsConstructor
@Slf4j
public class RestControllerImpl implements RestController {
@Override
public ResponseEntity<Void> send(Dto dto) {
return new ResponseEntity<>(HttpStatus.OK);
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
@RequiredArgsConstructor
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new ScopeAwareExpressionHandler();
}
@Bean
@Order(0)
SecurityFilterChain apiFilterChain(
HttpSecurity http,
@Value("${spring.security.oauth2.client.provider-uri}") String hostname
) throws Exception {
return http
.cors()
.configurationSource(request ->
new CorsConfiguration()
.applyPermitDefaultValues()
)
.and()
.csrf().disable()
.requestMatchers(
requestMatcherConfigurer -> requestMatcherConfigurer.antMatchers("/**")
)
.authorizeRequests(authorizeRequestsCustomized -> authorizeRequestsCustomized
.antMatchers(
"/swagger-ui/**"
)
.permitAll()
.anyRequest()
.authenticated()
)
.oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer ->
httpSecurityOAuth2ResourceServerConfigurer
.jwt()
.jwkSetUri(hostname + "/oauth2/jwks")
)
.build();
}
}
- application.yaml
spring:
security:
oauth2:
client:
registration:
my-service: # my-service
provider: spring
client-id: 1
client-secret:1
authorization-grant-type: client_credentials
scope: message.send
client-name: 1
provider:
spring:
issuer-uri:locachost....
user-info-uri: locachost..../api/v1/users/me
user-name-attribute: id
A想要为这个端点编写一个集成测试,以验证Oauth2凭据流客户端配置正确。首先,端点的功。
我怎么能那样做呢?
我没有找到任何适合我任务的例子。
有人能分享一下这个案子的知识吗?
如果您想编写集成测试:
- 启动授权服务器
- 脚本查询获得授权令牌与WebClient或其他
- 设置测试请求授权头与您得到的承载令牌。
我宁愿写单元测试与@WebmvcTest或@WebfluxTest bfluxTest和配置测试安全上下文与jwt() MockMvc后处理器(或Word bTestClient mutator)从spring-security-test或@WithMockJwtAuth从https://github.com/ch4mpy/spring-addons