java - 带有 client_credentials 错误的 Oaut2RestTemplate(不允许匿名)

标签 java spring spring-boot spring-security spring-oauth2

我正在尝试使用 ResourceServerConfigurerAdapter(使用 Oauth2 client_credentials)访问受 Spring Security 保护的 Web 服务

以下是安全配置

//Micoservice 1
@Configuration
@EnableResourceServer
class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Autowired
    private Environment env;

    @Autowired
    private DummyUserFilter dummyUserFilter;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(dummyUserFilter, LogoutFilter.class)
            .formLogin().disable()
            .httpBasic().disable()
            .csrf().disable()
            .antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/js/**", "/webjars/**").permitAll()
            .anyRequest()
                .authenticated();
    }
}

此应用程序(微服务 1)将由另一个具有 Oauth2RestTemplate 的应用程序(微服务 2)访问。以下是 Oauth2RestTemplate 配置。

//MicroService 2
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setAccessTokenUri("https://<UAA>/oauth/token");
        resourceDetails.setClientId("#####");
        resourceDetails.setClientSecret("#####");
        resourceDetails.setGrantType("client_credentials");
        resourceDetails.setTokenName("access_token");

        DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();

        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);

        return restTemplate;
    }
}

微服务 2 具有各种 Web 服务,这些服务使用 RestTemplate 访问 微服务 1 的 protected Web 服务。

这总是导致以下异常

需要身份验证才能获得访问 token (不允许匿名)

我搜索了一下这个错误,发现是在AccessTokenProviderChain中抛出的

这里是相关代码的github链接

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java#L89

if (auth instanceof AnonymousAuthenticationToken) {
    if (!resource.isClientOnly()) {
        throw new InsufficientAuthenticationException(
                "Authentication is required to obtain an access token (anonymous not allowed)");
    }
}

它似乎不允许匿名用户访问 Oauth2 token 。

我无意使用 Oauth2 保护客户端应用程序(微服务 2),我必须对预先配置的 Oauth2RestTemplate 使用 client_credentials

如何阻止 Spring 阻止匿名用户访问 token ?

我已经尝试在匿名用户的情况下使用虚拟身份验证填充 SecurityContextHolder,但没有成功。即使我确实成功了,这看起来也像是一个 hack。

最佳答案

我遇到了同样的问题并得出结论,具有多个实现者的 AccessTokenProvider 接口(interface)是罪魁祸首。默认情况下,OAuth2RestTemplate 实例化 AccessTokenProviderChain,它会尝试重新使用现有的登录上下文。但是,如果不存在这样的登录,则必然会失败。尝试

restTemplate.setAccessTokenProvider(new ResourceOwnerPasswordAccessTokenProvider());

在你的工厂方法中。这使用拥有其凭据的 token 提供程序,并且在其实现中根本不引用线程本地 SecurityContextHolder

关于java - 带有 client_credentials 错误的 Oaut2RestTemplate(不允许匿名),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43859430/

相关文章:

java - 如何使用 XPATH 搜索包含 JAVA 中的 Selenium 测试类的跨度

java - Linkedin Android SDK - 无法连接到 API (INVALID_REQUEST)

Java 的 Matcher 无法正确匹配输入

java - Spring 容器的多线程功能?

spring - 为什么我不能在 Spring MVC 中使用 Valid 参数和 RequestParam?

java - Spring Boot的Mybatis ResultHandler无法运行

json - 如何测试 Spring Boot Controller 的错误输出?

spring - 更改 Spring 输入验证语言

java - 在 Java 中生成 UUID 字符串的有效方法(不带破折号的 UUID.randomUUID().toString())

java - Spring 中 @Autowired 的替代方案,它不会在测试类设置之前初始化 bean