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

Oaut2RestTemplate with client_credentials error (anonymous not allowed)

我正在尝试使用 ResourceServerConfigurerAdapter(使用 Oauth2 client_credentials

访问受 Spring 安全保护的 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;
    }
}

Microservice 2 有各种 Web 服务,它们使用 RestTemplate 访问 Microservice 1.

的受保护 Web 服务

这总是导致以下异常

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

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

中抛出的

这是来自 github 的 link 相关代码

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 令牌。

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

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

我已经尝试在匿名用户的情况下使用虚拟身份验证填充 SecurityContextHolder,但没有成功。即使我这样做成功了,也似乎是 hack。

尝试在您的第二个微服务中启用 httpBasic() 安全性并使用默认用户名 ("user") 和由 spring 生成的密码登录。

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

restTemplate.setAccessTokenProvider(new ResourceOwnerPasswordAccessTokenProvider());

在你的工厂方法中。这使用了一个令牌提供者,该提供者拥有其凭据并且在其实现中根本不引用本地线程SecurityContextHolder

使用 AuthorizedFeignClient 或 AuthorizedUserFeignClient 代替 oauth2RestTemplate...