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
和@autowire
ing?另一方面,如果您使用的是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-