如何使用 OAuth2RestTemplate?

新手上路,请多包涵

我试图了解如何使用 OAuth2RestTemplate 对象来使用我的 OAuth2 安全 REST 服务(它在不同的项目下运行,让我们假设也在不同的服务器上等……)

我的 REST 服务的一个例子是:

 http://localhost:8082/app/helloworld

-> 访问此 URL 会产生错误,因为我未通过身份验证

要请求令牌,我会去:

 http://localhost:8082/app/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=**USERNAME**&password=**PASSWORD**

收到令牌后,我可以使用以下 URL(插入的示例令牌)连接到 REST API

 http://localhost:8082/app/helloworld/?access_token=**4855f557-c6ee-43b7-8617-c24591965206**

现在我的问题是如何实现可以使用此 OAuth2 安全 REST API 的第二个应用程序?我真的没有找到任何工作示例,您可以在其中提供用户名和密码(例如,来自登录表单),然后生成一个可以重新用于从 REST API 获取数据的令牌。

我目前尝试使用以下对象:

 BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails =  new BaseOAuth2ProtectedResourceDetails();
baseOAuth2ProtectedResourceDetails.setClientId("restapp");
baseOAuth2ProtectedResourceDetails.setClientSecret("restapp");
baseOAuth2ProtectedResourceDetails.setGrantType("password");
// how to set user name and password ???

DefaultAccessTokenRequest accessTokenRequest = new DefaultAccessTokenRequest();
OAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext(accessTokenRequest());

OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(baseOAuth2ProtectedResourceDetails,oAuth2ClientContext);

但这行不通:(

非常感谢任何想法、工作示例或教程的链接。

原文由 Joachim Seminck 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

您可以在此处找到编写 OAuth 客户端的示例:

在您的情况下,您不能只对所有内容使用默认类或基类,您有多个类 Implementing OAuth2ProtectedResourceDetails 。配置取决于您配置 OAuth 服务的方式,但从您的 curl 连接假设我建议:

 @EnableOAuth2Client
@Configuration
class MyConfig{

    @Value("${oauth.resource:http://localhost:8082}")
    private String baseUrl;
    @Value("${oauth.authorize:http://localhost:8082/oauth/authorize}")
    private String authorizeUrl;
    @Value("${oauth.token:http://localhost:8082/oauth/token}")
    private String tokenUrl;

    @Bean
    protected OAuth2ProtectedResourceDetails resource() {
        ResourceOwnerPasswordResourceDetails resource;
        resource = new ResourceOwnerPasswordResourceDetails();

        List scopes = new ArrayList<String>(2);
        scopes.add("write");
        scopes.add("read");
        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId("restapp");
        resource.setClientSecret("restapp");
        resource.setGrantType("password");
        resource.setScope(scopes);
        resource.setUsername("**USERNAME**");
        resource.setPassword("**PASSWORD**");
        return resource;
    }

    @Bean
    public OAuth2RestOperations restTemplate() {
        AccessTokenRequest atr = new DefaultAccessTokenRequest();
        return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
    }
}

@Service
@SuppressWarnings("unchecked")
class MyService {

    @Autowired
    private OAuth2RestOperations restTemplate;

    public MyService() {
        restTemplate.getAccessToken();
    }
}

不要忘记 @EnableOAuth2Client 在你的配置类上,我也建议尝试你正在使用的 url 首先使用 curl,也尝试使用调试器跟踪它,因为很多异常只是被消耗并且由于安全原因从未打印出来,因此很难找到问题所在。您应该使用 loggerdebug 启用集。祝你好运

我在 github 上上传了示例 springboot 应用程序 https://github.com/mariubog/oauth-client-sample 来描述你的情况,因为我找不到你的场景的任何示例。

原文由 mariubog 发布,翻译遵循 CC BY-SA 4.0 许可协议

在 @mariubog ( https://stackoverflow.com/a/27882337/1279002 ) 的回答中,我也在示例中使用了密码授予类型,但需要将客户端身份验证方案设置为表单。密码端点不支持范围,并且无需设置授权类型,因为 ResourceOwnerPasswordResourceDetails 对象在构造函数中自行设置。

 public ResourceOwnerPasswordResourceDetails() {
    setGrantType("password");
}

对我来说关键是 client_id 和 client_secret 没有被添加到表单对象中,如果 resource.setClientAuthenticationScheme(AuthenticationScheme.form); 没有被设置。

查看开关: org.springframework.security.oauth2.client.token.auth.DefaultClientAuthenticationHandler.authenticateTokenRequest()

最后,当连接到 Salesforce 端点时,需要将密码令牌附加到密码中。

 @EnableOAuth2Client
@Configuration
class MyConfig {

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

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

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

@Value("${security.oauth2.client.password-token}")
private String passwordToken;

@Value("${security.user.name}")
private String username;

@Value("${security.user.password}")
private String password;

@Bean
protected OAuth2ProtectedResourceDetails resource() {

    ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();

    resource.setAccessTokenUri(tokenUrl);
    resource.setClientId(clientId);
    resource.setClientSecret(clientSecret);
    resource.setClientAuthenticationScheme(AuthenticationScheme.form);
    resource.setUsername(username);
    resource.setPassword(password + passwordToken);

    return resource;
}

@Bean
 public OAuth2RestOperations restTemplate() {
    return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
    }
}

@Service
@SuppressWarnings("unchecked")
class MyService {
    @Autowired
    private OAuth2RestOperations restTemplate;

    public MyService() {
        restTemplate.getAccessToken();
    }
}

原文由 theINtoy 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题