如何解决Spring Security 5.1-使用WebClient获取客户端凭证流的令牌
这里的问题是您没有以正确的方式实例化WebClient。
由于您位于 客户端
,因此您无权访问OAuth2AuthorizedClientRepository
。该bean应该链接到您使用配置.oauth2Login()
上的方法声明登录到的资源服务器HttpSecurity
。这些细节在这里解释:Spring
Security 5 Oauth2登录。
同样,您在 客户端,
因此需要一个交换筛选器功能,该功能将触发向授权服务器的请求以获取JWT令牌。您可以使用ServerOAuth2AuthorizedClientExchangeFilterFunction
代替。
最好使用a WebClientCustomizer
在WebClient过滤器中添加交换过滤器功能。为什么呢 仅仅因为在Spring应用程序中注入aWebClient.Builder
将使您能够访问链接到Web交换的本机指标。
因此,您将使用UnAuthenticatedServerOAuth2AuthorizedClientRepository
如下所示的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 Security文档:Spring Security文档:UnAuthenticatedServerOAuth2AuthorizedClientRepository类。
我试图在以下GitHub项目中总结一个演示案例:GitHub-Spring Security OAuth2 Machine-To- Machine场景。
我希望这能为您提供有关WebClient配置的更多见解。请问您有什么问题。
解决方法
我正在尝试通过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();
}
并自动将Web客户端连接到测试,然后像这样调用它,
webClient.get().uri("http://localhost:" + port + "/web/it")
.attributes(ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("idp")).retrieve()
.bodyToMono(String.class).block();
我假设交换功能将获取访问令牌(如果可用),或者进行调用以从IDP获取新令牌。但是,它将始终失败,HttpSessionOAuth2AuthorizedClientRepository
因为the
HttpServletRequest
为null。
在总体测试看起来像这样的情况下,它可以自动配置为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,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客户端实现的文档。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。