Oaut2RestTemplate 与 client_credentials 错误(不允许匿名)

Posted

技术标签:

【中文标题】Oaut2RestTemplate 与 client_credentials 错误(不允许匿名)【英文标题】:Oaut2RestTemplate with client_credentials error (anonymous not allowed) 【发布时间】:2017-10-07 03:38:21 【问题描述】:

我正在尝试使用 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)将由另一个应用程序(微服务 2)使用Oauth2RestTemplate 访问。以下是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 的相关代码链接

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。

【问题讨论】:

现在我已经通过将 Oauth2RestTemplate 的创建完全与 Spring 分开来解决它。如果我为Oauth2RestTemplate 创建一个bean 或尝试自动装配它,Spring 会检测并尝试干扰它。所以我为 Oauth2RestTemplate 创建了我自己的单例类,它与 Spring 无关,现在它可以工作了。不过我期待一个真正的答案。 您是否尝试过使用OAuth2RestTemplate restTemplate 定义OAuth2RestTemplate 类型的restTemplate bean 而不是RestTemplate @autowireing?另一方面,如果您使用的是ClientCredentialResourceDetails,则抛出InsufficientAuthenticationException 是没有意义的,因为它显然会为isClientOnly() github.com/spring-projects/spring-security-oauth/blob/master/… 返回true。其他 Bean 有机会吗? 是的,我使用了 Oauth2RestTemplate,正如您在我在问题中发布的代码中看到的那样,它会引发相同的错误。我不认为还有另一个 bean,现在它通过创建自定义单例来工作。 【参考方案1】:

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

restTemplate.setAccessTokenProvider(new ResourceOwnerPasswordAccessTokenProvider());

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

【讨论】:

【参考方案2】:

尝试在您的第二个微服务中启用 httpBasic() 安全性并使用默认用户名(“用户”)登录它并在 spring 之前生成密码。

【讨论】:

这需要 Spring 知道用户,但是需要的身份验证机制是 client_credential,它不涉及用户。 对不起,之前我提到了第一个微服务。我将其更正为第二个微服务。我编辑了我的答案。尝试登录到我在答案中提到的第二个微服务。 我会试一试,但为什么需要这样做? 据我所知,这是因为 spring 不允许匿名用户继续使用 Oauth2。 "获取访问令牌需要身份验证(不允许匿名)"【参考方案3】:

使用 AuthorizedFeignClient 或 AuthorizedUserFeignClient 代替 oauth2RestTemplate...

【讨论】:

以上是关于Oaut2RestTemplate 与 client_credentials 错误(不允许匿名)的主要内容,如果未能解决你的问题,请参考以下文章

MetaException(message:For direct MetaStore DB connections, we don't support retries at the clien

json PHP服务中的SOAP服务在PHP中的SOAP客户端 - http://www.starstormdesign.de/soap-service-mit-einem-soap-client-

samba安装与配置

0408-服务注册与发现-Eureka常用配置

网络基础知识

2.Docker的架构