我们有一个使用spring-security-oauth2:1.0
的应用程序。我试图将其更改为较新版本spring-security-oauth2:2.0.7.RELEASE
。一些类被删除,一些包结构被更改,我设法整理所有这些东西,我能够没有任何问题启动服务器。但我在这里遇到一个奇怪的问题。
使用OAuth2 - 1.0 version
,当用户登录时,我们曾在GET
上发出/oauth/token
请求,例如:
它以前工作得很好。
当我尝试同样的事情时,首先由于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);
}
我尝试将POST
请求与上述网址相同,但我收到InsufficientAuthenticationException
错误消息
没有客户端身份验证。尝试添加适当的身份验证过滤器
这是因为POST
中的以下TokenEndpoint.java
请求控制器。当我调试时,我发现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令牌?
答案 0 :(得分:5)
我不知道以前的版本,但我对2.0.7有所了解。
我怀疑您的问题是您的TokenEndpoint安全性尝试针对您的用户服务验证您的客户端。
TokenEndpoint受// Get a compilation error since null was passed
var someInstance = new SomeObject(null);
保护。默认情况下,此过滤器将使用BasicAuthenticationFilter
实例,该实例本身包含AuthenticationManager
,它本身依赖于AuthenticationProvider
的实例。
诀窍是UserDetailsService
的这个特定实例必须基于客户端,而不是用户:这就是为什么有一个UserDetailsService
,它适应{ {1}}至ClientDetailsUserDetailsService
。
通常,当您使用框架的配置类ClientDetailsService
,UserDetailsService
等时,所有这些内容都已默认完成。
答案 1 :(得分:1)
我有同样的问题,我的application.yml有这一行:
servlet:
path: /auth
因此令牌地址为:/auth/oauth/token
我从application.yml中删除了路径,因此令牌路径变为:
/oauth/token
一切正常。
我希望这个帮助
答案 2 :(得分:1)
以下错误的问题之一可能是未执行身份验证。我在较旧的Spring实施中遇到了这个问题。
验证:
TokenEndpoint-> postAccessToken方法。检查Principal是否不为null。如果为null,则表示未执行基本身份验证。
添加过滤器的一种方法是使用:
@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer {
}
有关AbstractSecurityWebApplicationInitializer的更多信息可以在Spring文档中找到
答案 3 :(得分:0)
就我而言,我找到了这个配置:
<强> security.allowFormAuthenticationForClients(); //这里
它适用于我,试试吧
@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 {
}
}
答案 4 :(得分:0)
问题可能是因为打开了所有请求。您应该将其删除。
Lname