我们有一个使用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);
}
我已经尝试了一个POST
请求与上述URL相同,但我得到了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。但是我无法找到正确的解决方案。
6条答案
按热度按时间sxissh061#
我不知道以前的版本,但我知道一点关于2.0.7。
我怀疑您的问题是您的TokenEndpoint安全性尝试针对您的 * 用户 * 服务验证您的 * 客户端 *。
TokenEndpoint受
BasicAuthenticationFilter
保护。默认情况下,此筛选器将使用AuthenticationManager
示例,该示例本身包含AuthenticationProvider
,而AuthenticationProvider
本身依赖于UserDetailsService
的示例。诀窍在于,UserDetailsService
的此特定示例必须基于客户端,而不是基于用户:这就是为什么有ClientDetailsUserDetailsService
,它将ClientDetailsService
适配到UserDetailsService
。通常,当您使用框架的配置类
AuthorizationServerConfigurerAdapter
、@EnableAuthorizationServer
等时,所有这些操作都已经默认完成了。1aaf6o9v2#
我遇到了同样的问题,我的application.yml有这样一行:
因此令牌地址为:
/auth/oauth/token
我从application.yml中删除了路径,因此令牌路径变为:
/oauth/token
个一切都很好。
我希望这对你有帮助
cnwbcb6i3#
以下错误的问题之一,可能是没有执行身份验证。我在Spring的旧实现中遇到过这个问题。
请验证:
TokenEndpoint -〉postAccessToken方法。检查主体是否不为空。如果为空,则表示未执行基本身份验证。
添加过滤器的解决方案之一是用途:
有关AbstractSecurityWebApplicationInitializer的更多信息,请参见Spring文档
lnxxn5zx4#
在我例子中,我找到了以下配置:
安全性.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
对我很有效,试试吧
c90pui9n5#
此问题可能是由于打开所有请求造成的。您应该将其删除。
dl5txlt96#
我正在学习这个教程-使用Spring Boot构建API后端的实用指南。请参见https://www.infoq.com/minibooks/spring-boot-building-api-backend,但是使用最新的SpringBoot版本(2.7)
我遇到了这个问题:
org.springframework.security.authentication.InsufficientAuthenticationException: There is no client authentication. Try adding an appropriate authentication filter. at org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:91) ~[spring-security-oauth2-2.3.5.RELEASE.jar:na]
我的解决方案/修正是用
@EnableWebSecurity
注解WebSecurityGlobalConfig
,因为在原来的课程中这个注解是缺失的。所以添加这个注解已经为我修正了这个错误。