Spring Security 5.5如何自定义OAuth2令牌请求的Authorization头
解决方案
你可以通过自定义DefaultClientCredentialsTokenResponseClient的请求转换器,关闭客户端凭证的URL编码逻辑,完整配置如下:
import org.springframework.core.convert.converter.Converter; import org.springframework.http.HttpHeaders; import org.springframework.http.RequestEntity; import org.springframework.security.oauth2.client.*; import org.springframework.security.oauth2.client.endpoint.DefaultClientCredentialsTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequestEntityConverter; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; import java.nio.charset.StandardCharsets; import java.util.Base64; @Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { // 自定义令牌请求客户端,替换编码逻辑 DefaultClientCredentialsTokenResponseClient tokenResponseClient = new DefaultClientCredentialsTokenResponseClient(); tokenResponseClient.setRequestEntityConverter(buildNoEncodingConverter()); OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials(configurer -> configurer.accessTokenResponseClient(tokenResponseClient)) .build(); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } /** * 构造不执行URL编码的客户端凭证请求转换器,兼容Spring Security 5.5.0及更早版本行为 */ private Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>> buildNoEncodingConverter() { OAuth2ClientCredentialsGrantRequestEntityConverter converter = new OAuth2ClientCredentialsGrantRequestEntityConverter(); // 替换默认的Basic认证头构造逻辑,跳过URL编码步骤 converter.setClientAuthenticationConverter(clientRegistration -> { if (!ClientAuthenticationMethod.CLIENT_SECRET_BASIC.equals(clientRegistration.getClientAuthenticationMethod())) { return null; } String credentialStr = clientRegistration.getClientId() + ":" + clientRegistration.getClientSecret(); String base64Credential = Base64.getEncoder().encodeToString(credentialStr.getBytes(StandardCharsets.UTF_8)); HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.AUTHORIZATION, "Basic " + base64Credential); return headers; }); return converter; }
实现说明
Spring Security 5.5.1版本的补丁默认遵循RFC 6749 第2.3.1节要求,会先对客户端ID、客户端密钥做URL编码后再生成Basic认证头。上述代码直接跳过了URL编码步骤,认证头生成逻辑和5.5.0版本完全一致,可兼容不遵循规范的OAuth 2.0提供商。
内容的提问来源于stack exchange,提问作者Steve Riesenberg
相关产品推荐
相关产品推荐

