是否有更简单的方法来加载 Spring OAuth 客户端配置

Posted

技术标签:

【中文标题】是否有更简单的方法来加载 Spring OAuth 客户端配置【英文标题】:Is There an Easier Way to Load Spring OAuth Client Configuration 【发布时间】:2016-06-13 06:30:07 【问题描述】:

我正在为一组端点进行概念验证,这些端点需要能够相互调用并传递通过 OAuth 2 客户端凭据流获得的令牌。我正在使用 Spring Boot 和相关项目来构建这些端点,我很困惑为什么框架似乎对以下代码非常固执:

package com.example.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@Configuration
@EnableAutoConfiguration
@EnableOAuth2Client
@RestController
public class StuffClient 

    @Value("$security.oauth2.client.access-token-uri")
    private String tokenUrl;

    @Value("$security.oauth2.client.id")
    private String clientId;

    @Value("$security.oauth2.client.client-secret")
    private String clientSecret;

    @Value("$security.oauth2.client.grant-type")
    private String grantType;

    @Autowired
    private OAuth2RestOperations restTemplate;

    private String uri = "http://localhost:8082/stuff/";

    @RequestMapping(value = "/client/stuffName", method = RequestMethod.GET)
    public String client(@PathVariable("stuffName") String stuffName) 
        String request = uri + stuffName;
        return restTemplate.getForObject(request, String.class);
    

    @Bean
    public OAuth2RestOperations restTemplate(OAuth2ClientContext clientContext) 
        return new OAuth2RestTemplate(resource(), clientContext);
    

    @Bean
    protected OAuth2ProtectedResourceDetails resource() 
        ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId(clientId);
        resource.setClientSecret(clientSecret);
        resource.setGrantType(grantType);
        return resource;
    

以及随附的配置文件:

server:
  port: 8081

security:
  basic:
    enabled: false
  oauth2:
    client:
      id: test-client
      client-secret: test-secret
      access-token-uri: http://localhost:8080/uaa/oauth/token
      grant-type: client_credentials

上面的工作完全符合预期。如果我将 security.oauth2.client.id 更改为 security.oauth2.client.client-id(在 Java 代码和 YAML 中),我会收到 500 错误,其中第一行是:

org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException: Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it. 

如果我对所有实例变量的值进行硬编码,该代码也可以正常工作。实际上,在填充这些实例变量的每一种排列中,它似乎都可以正常工作,除了我使用@Valuesecurity.oauth2.client.client-id 的值填充clientId

所以我的主要问题是:框架实际上是否以这种非常具体的方式自以为是?如果是这样,为什么?而且,我可以利用这种固执己见来简化我的代码吗?

【问题讨论】:

我遇到了同样的问题,你解决了吗 【参考方案1】:

我不确定您使用的是哪个 spring-boot 版本。我正在使用 spring-boot 版本1.5.4.RELEASED 并简化您的代码,

你可以注入OAuth2ProtectedResourceDetailslike

@Autowired
private OAuth2ProtectedResourceDetails resource;

并将OAuth2RestTemplate 创建为

@Bean
@Primary
public OAuth2RestOperations restTemplate(OAuth2ClientContext clientContext) 
    return new OAuth2RestTemplate(resource, clientContext);

示例 yaml ..

### OAuth2 settings ### 
security:
  user:
    password: none
  oauth2:
    client:
      accessTokenUri: $auth-server/oauth/token
      userAuthorizationUri: $auth-server/oauth/authorize
      clientId: myclient
      clientSecret: secret
    resource:
      user-info-uri: $auth-server/sso/user
      jwt:
        keyValue: |
          -----BEGIN PUBLIC KEY-----
          your public key
          -----END PUBLIC KEY-----

然后,在控制器中使用restTemplate 实例作为

@Autowired
private OAuth2RestOperations restTemplate;

希望对你有所帮助。

【讨论】:

以上是关于是否有更简单的方法来加载 Spring OAuth 客户端配置的主要内容,如果未能解决你的问题,请参考以下文章

是否有更简单的方法来获取张量的切片,如下例所示?

在 JavaScript 中,是不是有更简单的方法来检查属性的属性是不是存在?

在 Tensorflow 2.0 中是不是有更简单的方法来执行模型层?

Spring OAuth - 重新加载资源ID和身份验证权限

是否有更简单的方法在 Roblox (Lua) 上的父对象中查找对象

发散问题——Spring容器及加载