栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Spring Security LDAP和记住我

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security LDAP和记住我

使用LDAP配置RememberMe功能存在两个问题:

  • 选择正确的RememberMe实现(令牌与PersistentTokens)
  • 使用Spring的Java配置对其进行配置

我将逐步进行这些操作。

基于令牌的“记住我”功能(

TokenbasedRememberMeServices
)在身份验证期间的工作方式如下:

  • 用户获得身份验证(再次获得广告),我们目前知道用户的ID和密码
  • 我们构造值username + expirationTime + password + staticKey并为其创建一个MD5哈希
  • 我们创建一个包含用户名+到期时间+计算出的哈希值的cookie

当用户希望返回该服务并使用“记住我”功能进行身份验证时,我们:

  • 检查cookie是否存在且未过期
  • 从cookie中填充用户ID,然后调用提供的UserDetailsS​​ervice,该服务应返回与用户ID相关的信息, 包括密码
  • 然后,我们根据返回的数据计算哈希值,并验证cookie中的哈希值是否与我们计算出的值匹配
  • 如果匹配,我们返回用户的Authentication对象

需要进行哈希检查过程,以确保没有人可以创建“伪造的”记住我的cookie,这将使他们冒充其他用户。问题在于,此过程依赖于从我们的存储库加载密码的可能性-
但这对于Active Directory是不可能的-我们无法基于用户名加载纯文本密码。

这使得基于令牌的实现不适合与AD配合使用(除非我们开始创建一些本地用户存储,其中包含密码或其他一些基于用户的秘密凭证,并且我不建议这种方法,因为我不知道您的应用程序,尽管这可能是一个好方法)。

另一个让我记住的实现是基于持久性令牌(

PersistentTokenbasedRememberMeServices
)的,它的工作方式如下(以某种简化的方式):

  • 当用户进行身份验证时,我们会生成一个随机令牌
  • 我们将令牌与有关的用户ID信息一起存储在存储器中
  • 我们创建一个包含令牌ID的cookie

当用户想要认证时,我们:

  • 检查我们是否具有带有令牌ID的cookie
  • 验证令牌ID是否存在于数据库中
  • 根据数据库中的信息加载用户数据

如您所见,虽然现在我们需要令牌存储(通常是数据库,我们可以使用内存进行测试),但不再需要密码,而无需使用密码验证。

这使我们进入了配置部分。基于持久令牌的基本配置请记住我,如下所示:

@Overrideprotected void configure(HttpSecurity http) throws Exception {    ....    String internalSecretKey = "internalSecretKey";    http.rememberMe().rememberMeServices(rememberMeServices(internalSecretKey)).key(internalSecretKey);} @Bean public RememberMeServices rememberMeServices(String internalSecretKey) {     BasicRememberMeUserDetailsService rememberMeUserDetailsService = new BasicRememberMeUserDetailsService();     InMemoryTokenRepositoryImpl rememberMeTokenRepository = new InMemoryTokenRepositoryImpl();     PersistentTokenbasedRememberMeServices services = new PersistentTokenbasedRememberMeServices(staticKey, rememberMeUserDetailsService, rememberMeTokenRepository);     services.setAlwaysRemember(true);     return services; }

此实现将使用内存令牌存储,应将其替换

JdbcTokenRepositoryImpl
为生产用。提供的
UserDetailsService
内容负责为用户加载其他数据,这些数据由从“记住我”cookie加载的用户ID标识。最简单的实现如下所示:

public class BasicRememberMeUserDetailsService implements UserDetailsService {     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {         return new User(username, "", Collections.<GrantedAuthority>emptyList());     }}

您还可以提供另一个

UserDetailsService
实现,根据需要从AD或内部数据库中加载其他属性或组成员身份。它可能看起来像这样:

@Beanpublic RememberMeServices rememberMeServices(String internalSecretKey) {    LdapContextSource ldapContext = getLdapContext();    String searchbase = "OU=Users,DC=test,DC=company,DC=com";    String searchFilter = "(&(objectClass=user)(sAMAccountName={0}))";    FilterbasedLdapUserSearch search = new FilterbasedLdapUserSearch(searchbase, searchFilter, ldapContext);    search.setSearchSubtree(true);    LdapUserDetailsService rememberMeUserDetailsService = new LdapUserDetailsService(search);    rememberMeUserDetailsService.setUserDetailsMapper(new CustomUserDetailsServiceImpl());    InMemoryTokenRepositoryImpl rememberMeTokenRepository = new InMemoryTokenRepositoryImpl();    PersistentTokenbasedRememberMeServices services = new PersistentTokenbasedRememberMeServices(internalSecretKey, rememberMeUserDetailsService, rememberMeTokenRepository);    services.setAlwaysRemember(true);    return services;}@Beanpublic LdapContextSource getLdapContext() {    LdapContextSource source = new LdapContextSource();    source.setUserDn("user@"+DOMAIN);    source.setPassword("password");    source.setUrl(URL);    return source;}

这会让您记住我的功能,该功能可与LDAP一起使用,并提供内部加载的数据,

RememberMeAuthenticationToken
这些数据将在中提供
SecurityContextHolder.getContext().getAuthentication()
。它还将能够重新使用您现有的逻辑来将LDAP数据解析为用户对象(
CustomUserDetailsServiceImpl
)。

作为单独的主题,问题中发布的代码也存在一个问题,您应该替换以下内容:

    authManagerBuilder .authenticationProvider(activeDirectoryLdapAuthenticationProvider()) .userDetailsService(userDetailsService())    ;

与:

    authManagerBuilder .authenticationProvider(activeDirectoryLdapAuthenticationProvider())    ;

仅在添加基于DAO的身份验证(例如针对数据库)时才应调用userDetailsS​​ervice,并且应使用用户详细信息服务的实际实现来调用。您当前的配置可能导致无限循环。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/378312.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号