Java Spring Security 5.1-使用WebClient获取客户端凭据流的令牌
我正试图通过Java Spring Security 5.1-使用WebClient获取客户端凭据流的令牌,java,spring,spring-boot,spring-security,Java,Spring,Spring Boot,Spring Security,我正试图通过webclient获取承载令牌,设置如下,以便在servlet应用程序中对安全资源服务器进行集成测试 spring: security: oauth2: client: registration: idp: clientId: id clientSecret: secret authorization-grant-type: client_credent
webclient
获取承载令牌,设置如下,以便在servlet应用程序中对安全资源服务器进行集成测试
spring:
security:
oauth2:
client:
registration:
idp:
clientId: id
clientSecret: secret
authorization-grant-type: client_credentials
scope: read
provider:
idp:
authorization-uri: myidp/authorization.oauth2
token-uri: myidp/token.oauth2
user-info-uri: myidp/userinfo.openid
user-name-attribute: name
还有豆子
@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations,
OAuth2AuthorizedClientRepository authorizedClients) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
// (optional) explicitly opt into using the oauth2Login to provide an access token implicitly
// oauth.setDefaultOAuth2AuthorizedClient(true);
// (optional) set a default ClientRegistration.registrationId
// oauth.setDefaultClientRegistrationId("client-registration-id");
return WebClient.builder().apply(oauth.oauth2Configuration()).build();
}
将webclient自动连接到测试并这样调用
webClient.get().uri("http://localhost:" + port + "/web/it")
.attributes(ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("idp")).retrieve()
.bodyToMono(String.class).block();
我的假设是,交换函数要么获取访问令牌(如果可用),要么调用IDP获取新令牌。但是,由于httpsessionauth2authorizedclientpository
以及HttpServletRequest
为空,它将始终失败
在整个测试看起来像这样的情况下,这会自动配置为IDP提供者配置一些bean
@SpringBootTest(classes = WebITApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith(SpringExtension.class)
@ActiveProfiles("web-it")
class WebJwtIt {
@LocalServerPort
private int port;
@Autowired
private WebClient webClient;
@Test
void testIdpJwt() {
String response = webClient.get().uri("http://localhost:" + port + "/web/it")
.attributes(ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("ping")).retrieve()
.bodyToMono(String.class).block();
assertThat(response).isEqualTo("pass");
}
@RestController
@SpringBootApplication
@ImportAutoConfiguration(IdpAutoConfiguration.class)
static class WebITApplication implements IdpSecurityAdapter {
@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations,
OAuth2AuthorizedClientRepository authorizedClients) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
// (optional) explicitly opt into using the oauth2Login to provide an access token implicitly
// oauth.setDefaultOAuth2AuthorizedClient(true);
// (optional) set a default ClientRegistration.registrationId
// oauth.setDefaultClientRegistrationId("client-registration-id");
return WebClient.builder().apply(oauth.oauth2Configuration()).build();
}
public static void main(String args[]) {
new SpringApplicationBuilder().profiles("web-it").build().run(WebITApplication.class, args);
}
@GetMapping
public String secured() {
return "secured";
}
@GetMapping("/web/it")
public String securedOne() {
return "pass";
}
@Override
public void configure(final HttpSecurity httpSecurity) throws IdpSecurityAdapterException {
try {
httpSecurity.oauth2Client();
} catch (Exception e) {
throw new IdpSecurityAdapterException("Failed to Configure Oauth2Client", e);
}
}
@Override
public IdpProvider getIdpProvider() {
return IdpProvider.MyIdp;
}
}
网络客户端是否可以为我获取令牌并将其添加到请求中?我知道,通过
spring-security oauth:OAuthRestTemplate可以实现这一点,并且阅读了我认为可以通过web客户端实现的文档。这里的问题是,您没有以正确的方式实例化WebClient
由于您位于客户端,因此无法访问OAuth2AuthorizedClient存储库
。这个bean应该链接到一个资源服务器,您可以使用HttpSecurity
配置上的.oauth2Login()
方法声明登录该服务器。以下详细说明:
同样,您是在客户端,所以您需要的是一个exchange筛选器函数,它将触发对授权服务器的请求,以获取JWT令牌。您可以改用服务器OAuth2AuthorizedClient ChangeFilterFunction
您最好使用WebClientCustomizer
在WebClient过滤器中添加exchange过滤器功能。为什么?因为在Spring应用程序中注入WebClient.Builder
将允许您访问链接到web Exchange的本机指标
因此,您将使用未经身份验证的服务器OAuth2AuthorizedClientRepository
bean的新实例构建WebClient,如下所示:
// Use injection to get an in-memory reposiroty or client registrations
@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations) {
// Provides support for an unauthenticated user such as an application
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
// Build up a new WebClientCustomizer implementation to inject the oauth filter
// function into the WebClient.Builder instance
return new WebClientSecurityCustomizer(oauth);
}
由于您在客户端,所以您没有将用户与流程关联,这就是为什么您不能使用任何授权的客户端存储库bean实例关联。检查Spring安全文档:
我试图总结以下GitHub项目中的一个演示案例:
我希望这能让您对WebClient配置有更多的了解。如果您有任何问题,请询问。这太棒了,到目前为止,您一定错过了这个回答!如果您处于Servlet环境中的后台线程/非http线程中,只想为任何读者添加,也应该清除这个问题。在SpringSecurity5.2中有一个合适的配置可用。我的web客户端有一个问题,它在调用资源服务器之前为每个请求获取一个访问令牌。你已经测试过了吗?很好的解释:)