Java 在Spring Security中授予密码的oAuth2客户端

Java 在Spring Security中授予密码的oAuth2客户端,java,spring,spring-security,oauth-2.0,Java,Spring,Spring Security,Oauth 2.0,我正在使用一组oAuth2保护的服务。当前的工作方式是:客户端使用用户名和密码登录。我把这些换成代币。我将令牌保留在会话中,并在每次调用服务时提交它。它可以工作,但问题是我完全是手动完成的,没有使用SpringSecurityOAuth2的很多支持。 下面是它的外观: <!-- Configure Authentication mechanism --> <authentication-manager alias="authenticationManager">

我正在使用一组oAuth2保护的服务。当前的工作方式是:客户端使用用户名和密码登录。我把这些换成代币。我将令牌保留在会话中,并在每次调用服务时提交它。它可以工作,但问题是我完全是手动完成的,没有使用SpringSecurityOAuth2的很多支持。 下面是它的外观:

<!-- Configure Authentication mechanism -->
<authentication-manager alias="authenticationManager">
    <authentication-provider ref="oAuth2AuthenticationProvider"/>
</authentication-manager>


<beans:bean id="oAuth2AuthenticationProvider" class="my.custom.Oauth2AuthenticationProvider">
    <beans:constructor-arg name="accessTokenUri" value="http://x.x.x.x/oauth/token"/>
    <beans:constructor-arg name="clientId" value="myClientId"/>
    <beans:constructor-arg name="clientSecret" value="myClientSecret"/>
    <beans:constructor-arg name="scope">
        <beans:list>
            <beans:value>myScope</beans:value>
        </beans:list>
    </beans:constructor-arg>
</beans:bean>

<beans:bean id="resourceOwnerPasswordAccessTokenProvider" class="org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider"/>
}

如您所见,它基本上确保令牌保留在安全范围内,在每次调用后端服务之前,我可以从中手动提取令牌。同样,我将在每次调用之前检查令牌的新鲜度。 这很好,但我确信我可以使用XML中Spring的oauth名称空间(我不使用Java配置)以更少配置的代码方式实现同样的功能。我发现的大多数示例包括oAuth服务器实现,我并不关心它,只是把我弄糊涂了


有人能帮我解决这个问题吗?

我浏览了SpringSecurityOAuth源代码和在线找到的其他解决方案,并将类似的解决方案混合在一起。我正在使用Java Config,但它可能会帮助您映射到xml配置,如下所示:

@Configuration
@EnableOAuth2Client
public class RestClientConfig {

    @Value("${http.client.maxPoolSize}")
    private Integer maxPoolSize;

    @Value("${oauth2.resourceId}")
    private String resourceId;

    @Value("${oauth2.clientId}")
    private String clientId;

    @Value("${oauth2.clientSecret}")
    private String clientSecret;

    @Value("${oauth2.accessTokenUri}")
    private String accessTokenUri;


    @Autowired
    private OAuth2ClientContext oauth2ClientContext;


    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public HttpClient httpClient() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(maxPoolSize);
        // This client is for internal connections so only one route is expected
        connectionManager.setDefaultMaxPerRoute(maxPoolSize);
        return HttpClientBuilder.create().setConnectionManager(connectionManager).build();
    } 

    @Bean
    public OAuth2ProtectedResourceDetails oauth2ProtectedResourceDetails() {
        ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
        details.setId(resourceId);
        details.setClientId(clientId);
        details.setClientSecret(clientSecret);
        details.setAccessTokenUri(accessTokenUri);
        return details;
    }

    @Bean
    public AccessTokenProvider accessTokenProvider() {
        ResourceOwnerPasswordAccessTokenProvider tokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
        tokenProvider.setRequestFactory(httpRequestFactory());
        return new AccessTokenProviderChain(
                  Arrays.<AccessTokenProvider> asList(tokenProvider)
                );
    }

    @Bean
    public OAuth2RestTemplate restTemplate() {
        OAuth2RestTemplate template = new OAuth2RestTemplate(oauth2ProtectedResourceDetails(), oauth2ClientContext);
        template.setRequestFactory(httpRequestFactory());
        template.setAccessTokenProvider(accessTokenProvider());
        return template;
    }   
}
然后,您可以使用RestTemplate方法正常发出请求,例如:

    String url = "http://localhost:{port}/api/users/search/findByUsername?username={username}";

    ResponseEntity<User> responseEntity = restTemplate.getForEntity(
            url, User.class, 8081, username);
stringurl=”http://localhost:{port}/api/users/search/findByUsername?username={username}”;
ResponseEntity ResponseEntity=restTemplate.getForEntity(
url,User.class,8081,用户名);
如果您想在线路上跟踪请求,可以将apache http客户端上的日志级别设置为调试,例如使用Spring Boot:


logging.level.org.apache.http=DEBUG

如果用户名和密码在帖子正文中怎么办?作为x-www-url-encoded@cosbor11我也这样问自己,发现我们可以使用
details.setClientAuthenticationScheme(AuthenticationScheme.form)ResourceOwnerPasswordResourceDetails
实例详细信息上的code>,以便通过HTTP正文而不是使用标头发送身份验证数据。
@Autowired
private OAuth2RestTemplate restTemplate;

restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("username", username);
restTemplate.getOAuth2ClientContext().getAccessTokenRequest().set("password", password);
    String url = "http://localhost:{port}/api/users/search/findByUsername?username={username}";

    ResponseEntity<User> responseEntity = restTemplate.getForEntity(
            url, User.class, 8081, username);