我已经设置了一个spring web应用程序,它使用keycloak作为授权服务器。该应用程序配置为使用oauth2Login,要求用户使用keycloak登录。web应用程序也被配置为oauth2Resourceserver,这样它的URL就可以通过在keycloak中定义的角色来保护,这些角色可以从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调用设置为资源服务器的其他应用程序。我使用了一个feign请求拦截器,它尝试将一个JWT令牌放入HTTP Bearer标头中,如下所示:
@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());
};
}当用户使用keycloak前端登录到应用程序时,上面的代码工作正常。
但是,当我不手动登录应用程序,而是使用keycloak-auth-client,以编程方式登录并尝试使用rest模板访问URL时,请求拦截器中的authorizedClientManager.authorize(authorizeRequest)方法抛出以下代码:
org.springframework.security.oauth2.client.ClientAuthorizationRequiredException: [client_authorization_required] Authorization required for Client Registration Id: keycloak这将导致登录html返回到RestTemplate,而不是预期的相关数据。
发布于 2020-12-03 04:55:34
仔细想想,这可能不是处理来自完全不同应用程序中创建的持有者令牌的身份验证的合适方式-我认为该应用程序应该负责重新授权自己的访问令牌。
如果用户确实是通过密钥罩登录的,那么这里从SecurityContext检索的身份验证对象就是OAuth2AuthenticationToken。如果调用来自具有JWT令牌的外部应用程序,该应用程序获取了该令牌,并在http头部中将其设置为“承载”,则身份验证对象为JwtAuthenticationToken。
希望这是区分这两种用例的合适方法。如果身份验证是OAuth2AuthenticationToken,则可以使用上面的代码成功地对其进行重新授权。如果它是一个JwtAuthenticationToken,那么我只需将令牌添加到承载Http头,并让资源服务器验证它,而不需要重新授权令牌,因为这应该由源应用程序完成。
https://stackoverflow.com/questions/64977317
复制相似问题