Spring Security OAuth - 未为Null资源配置提供程序管理器

时间:2017-07-07 02:36:27

标签: java spring-mvc curl oauth spring-security-oauth2

我尝试使用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 Controller的方法如下:

@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.

问题(S):

  1. 我在这里失踪了什么?这需要一些注释吗?是否有未设置或需要的属性?
  2. (请注意,内容类型必须是“application / x-www-form-urlencoded”...)

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

    2. 这可能是我在RequestParameters中设置的默认值吗?

    3. 如果成功,我该如何设置它以便在发出任何请求之前始终预先加载访问令牌?

3 个答案:

答案 0 :(得分: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编码为Authorization标头(基本认证)。这是client_credentials grant的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'

如果您需要发送用户名&amp;密码作为数据而不是授权标题,您可以添加resourceDetails.setAuthenticationScheme(AuthenticationScheme.form);这应该设置de username&amp;密码作为数据

答案 1 :(得分:2)

真正的原因是,您使用ResourceOwnerPasswordResourceDetails来访问"client_credentials"访问令牌。我们无法互换ResourceOwnerPasswordResourceDetailsClientCredentialsResourceDetails

ClientCredentialsResourceDetails中,您需要设置AccessTokenUri, ClientId, ClientSecretgrantType。 在ResourceOwnerPasswordResourceDetails中,您需要提供Username and Password以及AccessTokenUri, ClientId, ClientSecretGrantType

(某些authserver确实接受了password令牌请求而没有username and password。但是我会说这是错误的)

引用:Securing an existing API with our own solution

答案 2 :(得分:0)

这可能是因为服务器无法识别您发布到该特定网址的内容类型。 在您的CURL请求中,请尝试添加&#39; content-type:application / x-www-form-urlencoded&#39;对于使用http标头的自定义控制器。 Http headers

此外,您还没有为resourceDetails设置用户名和密码。 resourceDetails.setUserName(&#34;用户&#34); resourceDetails.setUserName(&#34;密码&#34);

如果这些不起作用,请尝试提取使用application / x-www-form-urlencoded编码的请求,并通过RestTemplate将其作为字符串传递,然后您就可以获得令牌。

如果您需要其他支持,请告诉我。

尝试下面给出令牌和字符串响应的代码。

enter image description here