【发布时间】:2018-02-28 12:15:01
【问题描述】:
在我的应用程序中,我试图将ActiveDirectory 身份验证与OAuth2 刷新令牌结合起来。
我能够通过ActiveDirectoryLdapAuthenticationProvider 成功进行身份验证。我还提供了LdapUserDetailsMapper 的自定义实现,它使用来自ActiveDirectory 的一些自定义属性填充UserDetails。这里的关键是这些属性上设置了机密标志,并且仅对用户本身可用(即,经过身份验证的用户可以为自己读取这些属性的值,但不能为其他人读取)。这些属性存储在Authentication 对象中,供应用程序在经过身份验证的用户的上下文中使用。
当我尝试向图片添加刷新令牌时,事情变得很棘手。刷新令牌要求我实现一个UserDetailsService,我必须提供新的UserDetails,只有一个用户名。由于机密标志,这是不可行的。即使我的应用程序中有一些能够浏览ActiveDirectory 的主帐户,我也无法检索机密属性。
所以我宁愿提供更多的原子实现,例如检查用户是否仍然处于活动状态的函数或提供一组更新的用户权限的函数。不幸的是,我在Spring Security 中没有找到这种级别的原子性。因此,对于刷新令牌,我似乎必须提供UserDetailsService 的实现。
如果我必须提供新的用户详细信息,我希望能够访问以前的用户 Authentication 对象。在这种情况下,我将检查用户,如果它仍然处于活动状态,我将从之前的Authentication 复制所有机密信息。问题是它似乎不可用。在UserDetailsService::loadUserByUsername() 被称为SecurityContextHolder.getContext() 的那一刻不包含用户身份验证。 UserDetailsService API 也无法进行身份验证 - 我只获取用户名。同时,用户的 Authentication 对象仅存在于 UserDetailsByNameServiceWrapper 类中的一个堆栈帧:
public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
return this.userDetailsService.loadUserByUsername(authentication.getName());
}
我最不想在这里做的事情是为所有用户机密信息实现一些内存存储,以便在我需要提供新的UserDetails 时使用。我已经拥有由Spring 管理的用户身份验证所需的所有信息,而我这样做似乎只是多余的。
问题列表如下:
- 如果您从应用程序安全架构的角度觉得我做错了什么,请告诉我
- 有没有办法在刷新令牌过程中告诉
Spring使用以前的UserDetails对象,这样如果用户仍然处于活动状态,应用程序就可以回答这个问题,并且应该发出一个新的访问令牌(而不是提供UserDetailsService)? - 有没有办法在调用
UserDetailsService::loadUserByUsername()期间获取以前的用户Authentication对象,以便我可以将其用作机密信息的来源? - 是否有其他我目前看不到的方法可以将刷新令牌添加到我的应用程序?
更新:
Here 我看到一个评论说你可以实现你自己的AuthenticationUserDetailsService 来解决这个问题。这个我不明白怎么办。它在AuthorizationServerEndpointsConfigurer 中硬编码,它始终创建UserDetailsByNameServiceWrapper 的实例,因此要提供您自己的实现,您必须干预AuthorizationServerEndpointsConfigurer 初始化过程。
【问题讨论】:
标签: java spring-security oauth-2.0 active-directory refresh-token