Spring Security OAuth - 提供程序管理器未针对空资源进行配置

我正在尝试使用Spring Secruity的OAuth API从外部发布的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'

运行此 curl 命令后,能够从外部服务获取访问令牌。

使用Spring Security OAuth API时:

<dependency>
   <groupId>org.springframework.security.oauth</groupId>
     <artifactId>spring-security-oauth2</artifactId>
     <version>2.1.1.RELEASE</version>
</dependency>

设置我的SpringMVC控制器的方法,如下所示:

@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;
}

当我从本地 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.

问题:

  1. 我在这里错过了什么?是否需要对此进行一些注释?是否存在未设置或需要的属性?

(请注意,内容类型需要为“application/x-www-form-urlencoded”...)

  1. 如何使用Spring Security OAuth API模仿工作curl命令?

  2. 它可能是我在请求参数中设置的默认值吗?

  3. 如果成功,如何对其进行设置,以便在发出任何请求之前始终预加载访问令牌?


答案 1

真正的原因是,您正在用于访问令牌请求。我们不能交换 和 .ResourceOwnerPasswordResourceDetails"client_credentials"ResourceOwnerPasswordResourceDetailsClientCredentialsResourceDetails

在 您需要设置 和 .在 中,您需要提供 和 。ClientCredentialsResourceDetailsAccessTokenUri, ClientId, ClientSecretgrantTypeResourceOwnerPasswordResourceDetailsUsername and PasswordAccessTokenUri, ClientId, ClientSecretGrantType

(某些身份验证服务器确实接受令牌请求,但没有 ..但我会说这是错误的)passwordusername and password

参考 : 使用我们自己的解决方案保护现有 API


答案 2

这就是我使用的内容:

@Bean
public RestTemplate oAuthRestTemplate() {
    ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
    resourceDetails.setId("1");
    resourceDetails.setClientId(oAuth2ClientId);
    resourceDetails.setClientSecret(oAuth2ClientSecret);
    resourceDetails.setAccessTokenUri(accessTokenUri);

    OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);

    return restTemplate;
}

正确的标头将设置为 bij 框架,但用户名/密码将作为授权标头(基本身份验证)进行 base64 编码。这是client_credentials授权的 OAuth2 规范。

检查 API 是否支持该规范:

curl -X POST \
'https://api.app.com/v1/oauth/token' \
-i -u 'client:secret' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials'

如果您需要将用户名和密码作为数据而不是授权标头发送,则可以添加此应将de用户名和密码设置为数据resourceDetails.setAuthenticationScheme(AuthenticationScheme.form);


推荐