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.TokenEndpointpostAccessToken()几乎相同

在上面的屏幕截图中,我们可以看到 userDetailsS​​ervice 是 UserDetailsS​​erviceImpl 并且由于请求标头中存在此客户端详细信息,因为 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安全主体用户已更改为新登录的用户详细信息

为spring webservice添加密码安全性

Spring Boot OAuth2 - 无法从令牌获取用户详细信息

2023年网络安全比赛--跨站脚本攻击①中职组(超详细)