Spring security 以编程方式访问spring security OAuth2 5.3时,使用OAuth2AuthorizedClient Manager设置BearToken

Spring security 以编程方式访问spring security OAuth2 5.3时,使用OAuth2AuthorizedClient Manager设置BearToken,spring-security,spring-security-oauth2,Spring Security,Spring Security Oauth2,我已经建立了一个SpringWeb应用程序,它使用KeyClope作为授权服务器。 该应用程序被配置为使用oauth2Login,要求用户使用KeyClope登录。 web应用程序还被配置为oauth2Resourceserver,以便其URL可以使用KeyClope中定义的角色进行保护,这些角色可以从JWT自定义转换为JwtAuthenticationToken。配置如下所示: @Configuration @EnableWebSecurity public class WebSecurity

我已经建立了一个SpringWeb应用程序,它使用KeyClope作为授权服务器。 该应用程序被配置为使用oauth2Login,要求用户使用KeyClope登录。 web应用程序还被配置为oauth2Resourceserver,以便其URL可以使用KeyClope中定义的角色进行保护,这些角色可以从JWT自定义转换为JwtAuthenticationToken。配置如下所示:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(authorizeRequests ->
                authorizeRequests.antMatchers("/test*").hasAnyRole("Dev", "QA")
                                 .anyRequest().authenticated())
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(this.keycloakJwtAuthenticationConverter())))
            .oauth2Login(oauth2 -> oauth2.userInfoEndpoint(userInfo -> userInfo.userAuthoritiesMapper(this.userAuthoritiesMapper())))
            .oauth2Client();
    }
    ...
该应用程序还充当oauth2Client,它使用open-Feign调用其他设置为资源服务器的应用程序。我使用一个伪请求拦截器,尝试将JWT令牌放入HTTP承载头,如下所示:

@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;

@Bean
public RequestInterceptor requestInterceptor() {

    return requestTemplate -> {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("keycloak")
                                                                        .principal(authentication)
                                                                        .build();
        OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
        OAuth2AccessToken accessToken = authorizedClient.getAccessToken();

        requestTemplate.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken.getTokenValue());
    };
}
当用户使用KeyClope前端登录应用程序时,上述代码正常工作

但是,当我不手动登录应用程序,而是使用KeyClope auth client以编程方式登录并尝试使用HTTP承载头中生成的JWT令牌集填充的rest模板访问URL时,请求拦截器中的authorizedClientManager.Authorized(authorizeRequest)方法抛出以下内容:

org.springframework.security.oauth2.client.ClientAuthorizationRequiredException: [client_authorization_required] Authorization required for Client Registration Id: keycloak

这将导致登录html返回到RestTemplate,而不是预期的相关数据。

经过反思,这可能不是处理来自在完全不同的应用程序中创建的承载令牌的身份验证的适当方法-我认为应用程序应该负责重新授权其自己的访问令牌

如果用户确实通过KeyClope登录,则从SecurityContext检索的身份验证对象是OAuth2AuthenticationToken。如果调用来自具有JWT令牌的外部应用,该JWT令牌已获取并在http头中将其设置为“承载者”,则身份验证对象是JwtAuthenticationToken


希望这是区分这两个用例的合适方法。如果身份验证是OAuth2AuthenticationToken,则可以使用上述代码成功地对其进行重新身份验证。如果它是JwtAuthenticationToken,那么我只需将该令牌添加到承载http头中,并让资源服务器验证它,而无需重新授权该令牌,因为这应该由源应用程序完成。

经过反思,这可能不是处理来自在完全不同的应用程序中创建的承载令牌的身份验证的适当方法-我认为应用程序应该负责重新授权其自己的访问令牌

如果用户确实通过KeyClope登录,则从SecurityContext检索的身份验证对象是OAuth2AuthenticationToken。如果调用来自具有JWT令牌的外部应用,该JWT令牌已获取并在http头中将其设置为“承载者”,则身份验证对象是JwtAuthenticationToken

希望这是区分这两个用例的合适方法。如果身份验证是OAuth2AuthenticationToken,则可以使用上述代码成功地对其进行重新身份验证。如果它是JwtAuthenticationToken,那么我可以将该令牌添加到承载http头中,并让资源服务器验证它,而无需重新授权该令牌,因为这应该由源应用程序完成