Spring 安全客户端详细信息将作为 DaoAuthenticationProvider 中的用户详细信息
Posted
技术标签:
【中文标题】Spring 安全客户端详细信息将作为 DaoAuthenticationProvider 中的用户详细信息【英文标题】:Spring security client detail is going as user detail in DaoAuthenticationProvider 【发布时间】:2017-10-02 04:29:05 【问题描述】:Spring Boot,安全 OAuth2 实现,默认令牌端点 (/oauht/token) 工作正常。但是,当我在 /oauth/http/token 向新端点发送请求时,由于以下原因,它会抛出 Bad Credentials:
FilterChainProxy
触发大约 12 个过滤器,其中一个是 BasicAuthenticationFilter
。它使用DaoAuthenticationProvider
类的UserDetailsService
来获取用户数据。对于客户端身份验证,这应该是ClientDetailsService
,但由于某种原因,这始终是UserDetailsService
,并且由于此客户端凭据转到UserRepository
并失败。这个类确实可以正确初始化,因为默认 /oauth/token
可以正常工作。
我尝试在BasicAuthenticationFilter
中注入现有的身份验证管理器,并将其添加为ResourceServerConfigurerAdapter
中的过滤器,但这没有任何区别。它确实将身份验证管理器提供程序从AnonymousAuthenticationProvider
更改为DaoAuthenticationProvider
,但UserDetailsService
仍然是UserDetails
。
在/oauth/http/token
请求,这不起作用。代码与org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
的postAccessToken()
几乎相同
在上面的屏幕截图中,我们可以看到 userDetailsService 是 UserDetailsServiceImpl 并且由于请求标头中存在此客户端详细信息,因为 Basic dGVzdDpwYXNzd29yZA==
将进入用户存储库并在用户表中检查,而不是转到客户端存储库并在客户端表中检查。
在/oauth/token
请求,这可行
【问题讨论】:
【参考方案1】:FilterChainProxy
维护的不是单个过滤器链,而是SecurityFilterChain
-s 的列表。每个安全过滤器链都包含一个请求匹配器和一个过滤器列表。因此,您将在这些不同的链中拥有多个 BasicAuthenticationFilter
实例。
将触发哪个过滤器链取决于传入的请求和请求匹配器的决定。
/oauth/token
触发由 spring oauth 创建的链,最后使用ClientDetailsService
。
/oauth/http/token
触发由您的网络安全配置创建的另一个链并使用用户详细信息服务。
所以……这就是原因。要查看启动时如何创建链,您可以启用安全调试,例如在application.yml
logging:
level:
org.springframework.security: DEBUG
然后你会看到oauth安全链的创建:
Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4ce4e309, org.springframework.security.web.context.SecurityContextPersistenceFilter@16331720, org.springframework.security.web.header.HeaderWriterFilter@60ef29a5, org.springframework.security.web.authentication.logout.LogoutFilter@4c9638cc, org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter@9eefda5, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@16d090e9, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@484a9950, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1c4fefe8, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@12082780, org.springframework.security.web.session.SessionManagementFilter@20a49b7b, org.springframework.security.web.access.ExceptionTranslationFilter@24313d10, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@47ce08d2]
注意请求匹配器。
更新:如果您想将端点“重新映射”到您自己的端点,您可以重新配置它。
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception
endpoints.pathMapping("/oauth/token", "/oauth/http/token");
【讨论】:
感谢您的回复。检查您的回复后,我添加了http.userDetailsService(clientDetailsUserDetailsService);
,并且正在搜索此客户端表,但正在执行身份验证的BasicAuthenticationFilter
使用PlaintextPasswordEncoder
,而不是DaoAuthenticationProvider
中定义的密码编码器。我使用自定义身份验证管理器添加了自定义 BasicAuthenticationFilter
,但使用此用户表搜索客户端 ID。无论如何我可以复制 Spring oauth 创建的默认 /oauth/token 吗?
除了pathMapping()
,是否有任何代码可以覆盖并添加一些 URL,这些 URL 将使用与 /outh/token 使用的完全相同的过滤器链
我不确定您想要或应该(不)做什么,但您可以使用 AuthorizationServerSecurityConfigurer#addTokenEndpointAuthenticationFilter
向 oauth 链添加额外的过滤器。过滤器链通过WebSecurityConfigurerAdapter
管理,OAuth 的过滤器链来自@EnableAuthorizationServer
。作者通过AuthorizationServerConfigurerAdapter
类公开了所有有效配置。
谢谢兰切萨。我最终在AuthorizationServerSecurityConfiguration
中使用了类似的配置。在configure(HttpSecurity http)
我添加了自定义端点匹配器并获得了相同的过滤器链(/oauth/token)。
@VijayNandwana 你能分享一下你是如何解决这个问题的吗?以上是关于Spring 安全客户端详细信息将作为 DaoAuthenticationProvider 中的用户详细信息的主要内容,如果未能解决你的问题,请参考以下文章
使用 grails spring security rest 插件登录时获取用户详细信息
Java - Spring 的 ReactorNettyWebSocketClient 线程安全吗?
Spring Boot安全主体用户已更改为新登录的用户详细信息