如何为 OAuth2RestTemplate 设置 HTTP 标头

Pac*_*ver 5 java curl spring-security oauth-2.0 spring-security-oauth2

我尝试使用 Spring Secruity 的 OAuth API 从基于 Spring MVC 4 的 Web 服务(不是 Spring Boot)中外部发布的 API 获取访问令牌。

这个curl命令有效(它的内容是我获取访问令牌所需的全部内容):

curl -X POST \
https://api.app.com/v1/oauth/token \
  -H 'content-type: application/x-www-form-urlencoded' \
  -d'grant_type=client_credentials&client_id=bcfrtew123&client_secret=Y67493012'
Run Code Online (Sandbox Code Playgroud)

Spring Security OAuth API:

<dependency>
   <groupId>org.springframework.security.oauth</groupId>
     <artifactId>spring-security-oauth2</artifactId>
     <version>2.1.1.RELEASE</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

我获取访问令牌的代码:

@RequestMapping(value = "/getAccessToken", method = RequestMethod.POST, consumes="application/x-www-form-urlencoded")
public OAuth2AccessToken getAccessToken(@RequestParam(value="client_id", required=true) String clientId, @RequestParam(value="client_secret", required=true) String clientSecret) throws Exception {
    String tokenUri = "https://api.app.com/v1/oauth/token";

    ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();

    resourceDetails.setAccessTokenUri(tokenUri);
    resourceDetails.setClientId(clientId);
    resourceDetails.setClientSecret(clientSecret);
    resourceDetails.setGrantType("client_credentials");
    resourceDetails.setScope(Arrays.asList("read", "write"));

    DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();

    oauth2RestTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);

    OAuth2AccessToken token = oauth2RestTemplate.getAccessToken();
    return token;
}
Run Code Online (Sandbox Code Playgroud)

当我从本地 tomcat 实例调用 getAccessToken 时:

access_denied 
error_description=Unable to obtain a new access token for resource 'null'. 
The provider manager is not configured to support it.
Run Code Online (Sandbox Code Playgroud)

我怀疑原因是我的 Http 标头的 Content-Type 未设置为

application/x-www-form-urlencoded
Run Code Online (Sandbox Code Playgroud)

我该如何设置:

import org.springframework.security.oauth2.client.OAuth2RestTemplate;
Run Code Online (Sandbox Code Playgroud)

如果您注意到,我正在尝试在 @RequestMapping 内部进行设置,但不认为它有效:

@RequestMapping(consumes="application/x-www-form-urlencoded") 
Run Code Online (Sandbox Code Playgroud)

小智 3

在客户端凭据的情况下,用于访问 Oauth2Restemplate 中的令牌的 http 标头在 ClientCredentialsAccessTokenProvider 的以下方法中设置(因为授权类型是客户端凭据)

public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request)
        throws UserRedirectRequiredException, AccessDeniedException, 
OAuth2AccessDeniedException {

ClientCredentialsResourceDetails resource = (ClientCredentialsResourceDetails) details;
return retrieveToken(request, resource, getParametersForTokenRequest(resource), new HttpHeaders());

}
Run Code Online (Sandbox Code Playgroud)

我们可以通过为客户端凭据提供新的自定义访问令牌提供程序并修改方法来设置 http 标头,如下所示:

public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request)
        throws UserRedirectRequiredException, AccessDeniedException, OAuth2AccessDeniedException {

ClientCredentialsResourceDetails resource = (ClientCredentialsResourceDetails) details;

    HttpHeaders headers1 = new HttpHeaders();

    headers1.add("Content-Type", "application/x-www-form-urlencoded");

    return retrieveToken(request, resource, getParametersForTokenRequest(resource), headers1);

}
Run Code Online (Sandbox Code Playgroud)

您可以保持类与 ClientCredentialsAccessTokenProvider 相同,并仅添加标题行。

最后一步是在 Oauth2RestTemplate 配置中将此新类设置为访问令牌。

oauth2RestTemplate.setAccessTokenProvider(new ClientCredentialsCustomAccessTokenProvider());
Run Code Online (Sandbox Code Playgroud)

这对我有用!