Spring OAuth2 - 没有客户端身份验证。尝试添加适当的身份验证过滤器
Posted
技术标签:
【中文标题】Spring OAuth2 - 没有客户端身份验证。尝试添加适当的身份验证过滤器【英文标题】:Spring OAuth2 - There is no client authentication. Try adding an appropriate authentication filter 【发布时间】:2015-10-08 20:54:03 【问题描述】:我们有一个使用spring-security-oauth2:1.0
的应用程序。我试图将其更改为较新的版本,spring-security-oauth2:2.0.7.RELEASE
。删除了一些类,更改了一些包结构,我设法解决了所有这些问题,并且能够毫无问题地启动服务器。但我在这里遇到了一个奇怪的问题。
使用OAuth2 - 1.0 version
,当用户登录时,我们曾经对/oauth/token
进行GET
请求,例如:
http://localhost:8080/echo/oauth/token?grant_type=password&client_id=ws&client_secret=secret&scope=read,write&username=john@abc.com&password=password123
它曾经工作得很好。
当我尝试同样的事情时,首先由于TokenEndPoint.java 中的逻辑,我无法发出GET
请求
private Set<HttpMethod> allowedRequestMethods = new HashSet<HttpMethod>(Arrays.asList(HttpMethod.POST));
@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException
if (!allowedRequestMethods.contains(HttpMethod.GET))
throw new HttpRequestMethodNotSupportedException("GET");
return postAccessToken(principal, parameters);
我尝试发出与上述 URL 相同的 POST
请求,但我收到带有错误消息的 InsufficientAuthenticationException
没有客户端身份验证。尝试添加适当的身份验证过滤器
这是因为TokenEndpoint.java
中的以下POST
请求控制器。当我调试时,我看到principal
为空。
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException
//principal is null here
if (!(principal instanceof Authentication))
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
.............
我有一个身份验证过滤器,当我使用version 1.0
时它运行良好。这是我配置的相关部分:
<authentication-manager xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userDetailsService"/>
</authentication-manager>
<bean id="userDetailsService" class="com.hcl.nc.service.UserDetailsService">
<constructor-arg><ref bean="sessionFactory" /></constructor-arg>
</bean>
我一直认为请求将由authentication-provider
进行身份验证并转到token-endpoint
但这似乎不是正确的流程。用version 2.0.7
调试应用程序后,现在我真的怀疑我对流程的理解了。
有人能解释一下为什么它在以前的版本中可以工作,为什么现在不能工作吗?
我是否需要做一些不同的事情才能获得 OAuth 令牌?
注意:我已经检查了这些问题:here、here、here。但我找不到正确的解决方案。
【问题讨论】:
你找到答案了吗?我遇到了同样的问题,在这里找不到答案。 【参考方案1】:我不知道之前的版本,但是我对2.0.7有点了解。
我怀疑您的问题是您的 TokenEndpoint 安全尝试针对您的 user 服务对您的 clients 进行身份验证。
TokenEndpoint 受BasicAuthenticationFilter
保护。默认情况下,此过滤器将使用AuthenticationManager
实例,该实例本身包含AuthenticationProvider
,它本身依赖于UserDetailsService
的实例。
诀窍是UserDetailsService
的这个特定实例必须基于客户端,而不是基于用户:这就是为什么有一个ClientDetailsUserDetailsService
,它使ClientDetailsService
适应@ 987654328@.
通常,当您使用框架的配置类AuthorizationServerConfigurerAdapter
、@EnableAuthorizationServer
等时,所有这些东西已经默认完成。
【讨论】:
那么当我使用 xml 配置时,这些东西是如何完成的呢?【参考方案2】:就我而言,我找到了这个配置:
security.allowFormAuthenticationForClients(); // 这里
然后发布这个 http://localhost:8081/sso/oauth/token?client_id=unity-client&client_secret=unity&grant_type=authorization_code&code=Yk4Sum&redirect_uri=http://localhost:8082/sso-demo/passport/login
它对我有用,试试吧
@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter
private static final Logger log = LoggerFactory.getLogger(Oauth2Config.class);
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception
security.allowFormAuthenticationForClients(); // here
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception // @formatter:off
clients.inMemory()
.withClient("unity-client")
.secret("unity")
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
.scopes("foo", "read", "write")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
;
// @formatter:on
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception
【讨论】:
【参考方案3】:我遇到了同样的问题,我的 application.yml 有这一行:
servlet:
path: /auth
所以令牌地址是:/auth/oauth/token
我从 application.yml 中删除了路径,因此令牌路径变为:
/oauth/token
一切正常。
希望对你有帮助
【讨论】:
虽然这不是我一直在寻找的解决方案,但给了我方向和异常的根本原因。如果有人知道如何使用 oauth 和 servlet 上下文,请告诉我。【参考方案4】:以下错误的问题之一可能是未执行身份验证。我在 Spring 的旧实现中遇到了这个问题。
验证:
TokenEndpoint -> postAccessToken 方法。检查 Principal 是否不为空。如果为空,则表示未执行基本授权。
添加过滤器的解决方案之一是使用:
@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer
有关 AbstractSecurityWebApplicationInitializer 的更多信息可以在 Spring 文档中找到
【讨论】:
【参考方案5】:问题可能是因为打开了所有请求。你应该删除它。
@Override
public void configure(WebSecurity web) throws Exception
web
.ignoring()
.antMatchers("/**");
【讨论】:
以上是关于Spring OAuth2 - 没有客户端身份验证。尝试添加适当的身份验证过滤器的主要内容,如果未能解决你的问题,请参考以下文章
没有客户端身份验证。尝试添加适当的身份验证过滤器异常 spring oauth2
Spring OAuth2 禁用 TokenEndpoint 的 HTTP 基本身份验证
如何使用 Spring Boot feign 客户端进行 Oauth2 身份验证?
使用 Spring Security 自定义客户端身份验证的 OAuth2 错误响应