Oauth 2.0 如何在spring security oauth 2.2.1.RELEASE中使用客户端凭据和自动令牌刷新设置OAuth2RestTemplate

Oauth 2.0 如何在spring security oauth 2.2.1.RELEASE中使用客户端凭据和自动令牌刷新设置OAuth2RestTemplate,oauth-2.0,access-token,spring-security-oauth2,refresh-token,Oauth 2.0,Access Token,Spring Security Oauth2,Refresh Token,我正在实现一个客户端,该客户端使用OAuth2对WSO2进行身份验证,我在刷新访问令牌时遇到了严重问题,导致401未经授权。虽然我已经发现了SpringOAuth2代码的作用,但我不知道为什么它的行为在2.2.1.RELEASE中发生了变化,在我看来,这显然是错误的。实际上使用2.0.14.0版本是可行的 在我向你们展示我所做的和我已经发现的之前,让我先阐述一下我的问题: 我应该如何实现OAuth2客户端,使用客户端凭据而不是用户凭据自动刷新令牌 这就是我到目前为止所实现的。客户端使用Resou

我正在实现一个客户端,该客户端使用OAuth2对WSO2进行身份验证,我在刷新访问令牌时遇到了严重问题,导致401未经授权。虽然我已经发现了SpringOAuth2代码的作用,但我不知道为什么它的行为在2.2.1.RELEASE中发生了变化,在我看来,这显然是错误的。实际上使用2.0.14.0版本是可行的

在我向你们展示我所做的和我已经发现的之前,让我先阐述一下我的问题:

我应该如何实现OAuth2客户端,使用客户端凭据而不是用户凭据自动刷新令牌

这就是我到目前为止所实现的。客户端使用
ResourceOwnerPasswordResourceDetails
配置
OAuth2RestTemplate
,使用
IsClient
标记
true
,因为没有用户会话。可以成功建立客户端会话,并设置访问令牌和刷新令牌

@Bean
protected OAuth2ProtectedResourceDetails resource() {
    ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails() {
        @Override
        public boolean isClientOnly() {
            return true;
        }               
    };
    List<String> scopes = new ArrayList<>(2);
    scopes.add("write");
    scopes.add("read");
    resource.setScope(scopes);
    resource.setGrantType("password");
    resource.setAccessTokenUri(TOKEN_URL);
    resource.setClientId(MY_CLIENT_ID);
    resource.setClientSecret(MY_CLIENT_SECRET);
    resource.setUsername(MY_SERVICE_USER);
    resource.setPassword(MY_SERVICE_USER_PW);
    return resource;
}


@Bean
public OAuth2RestOperations restTemplate() {
    AccessTokenRequest atr = new DefaultAccessTokenRequest();
    OAuth2RestTemplate template = new OAuth2RestTemplateWithBasicAuth(resource(), new DefaultOAuth2ClientContext(atr));
    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
    interceptors.add(new LoggingRequestInterceptor());      
    template.setInterceptors(interceptors);
    template.setRetryBadAccessTokens(true);
    return template;
}
如您在P1所见,如果存在授权用户会话(
auth
),或者资源配置为
clientOnly
,则会进入该块。由于我没有用户,但我处于链接服务场景中,因此我有
isClientOnly()==true&&auth==null
。但在P2,实际执行刷新的最终决定与要求
相反!isClient()
。因此,这有效地禁止了仅客户端场景中的刷新请求

这是进入2.2.1之前版本的方式,我发现,这似乎是对以下内容的修复。在我看来,这显然是错误的

此外,在我看来,该补丁似乎破坏了客户端功能,以修复实际的服务器错误行为。正如您在问题讨论中所看到的,我已经在那里对问题进行了评论。但是,由于这个问题已经结束,spring-security-oauth2论坛声明应该在这里就StackOverflow进行讨论,我在这里请求帮助


又是一个问题:如何配置客户端应用程序,通过OAuth2RestTemplate和一小时的访问令牌运行时间以及两小时的刷新令牌运行时间来使用OAuth2安全服务。

我将标题改为一个问题,以符合StackOverflow格式。很抱歉,没有立即纠正。其他频道上的第一个响应表明,问题在于使用用户会话专用授权类型“密码”而不是授权类型“客户端凭据”。后者应用于服务到服务的身份验证,并且根本不使用令牌刷新,而是始终重新登录。这可以解释V2.2.1.1版本中的更改。但在我的场景中,身份验证服务器没有配置为通过客户端\ U凭据提供访问,目前我无法更改这一点。因此,很不幸,我仍然必须使用“密码”授权来设置连接。您是否设法解决了此问题?@Minisha:在该项目中,我明确地必须坚持旧的spring-security-oauth2:2.0.14.RELEASE。从那时起,在新的项目中,我将Spring全部抛弃,并使用akka http或dispatch http基于Scala。解决方案更加灵活和透明(顺便说一句,速度更快)。
    if (resource.isClientOnly() || (auth != null && auth.isAuthenticated())) {   // P1
        existingToken = request.getExistingToken();
        if (existingToken == null && clientTokenServices != null) {
            existingToken = clientTokenServices.getAccessToken(resource, auth);
        }

        if (existingToken != null) {
            if (existingToken.isExpired()) {
                if (clientTokenServices != null) {
                    clientTokenServices.removeAccessToken(resource, auth);
                }
                OAuth2RefreshToken refreshToken = existingToken.getRefreshToken();
                if (refreshToken != null && !resource.isClientOnly()) {  // P2
                    accessToken = refreshAccessToken(resource, refreshToken, request);
                }
            }
            else {
                accessToken = existingToken;
            }
        }
    }