`
lengyun3566
  • 浏览: 453730 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
D59180b9-02f1-3380-840c-ea34da46143c
《Spring Secur...
浏览量:384275
社区版块
存档分类
最新评论

《Spring Security3》第九章(LDAP)第二部分翻译(LDAP高级配置)

阅读更多

 

LDAP的高级配置

         一旦我们要了解LDAP基础集成之外的知识,就会发现security XML命名空间方式的配置中,Spring Security LDAP模块还有许多的可用配置。它包括查询用户的个人信息、用户认证的其它方式以及使用LDAP作为UserDetailsService且与DaoAuthenticationProvider结合。

实例JBCP LDAP用户

         JBCP Pets LDIF文件中,我们提供了许多的用户。在高级配置练习和自学中,以下的快速查询表可能会对你有所帮助。要注意的是除了userwithphone以外,所有用户的密码均为password

        

用户名

角色

密码编码

ldapguest

ROLE_USER

Plaintext

anotherldapuser

ROLE_USER

Plaintext

ldapadmin

ROLE_USERROLE_ADMIN

Plaintext

shapassworduser

ROLE_USER

{sha}

sshapassworduser

ROLE_USER

{ssha}

userwithphone

ROLE_USER

Plaintext(在telephoneNumber属性中)

 

         我们将会在后面的章节中介绍为什么密码编码很重要。

密码对比与绑定认证

         有一些LDAP服务器可能会配置成不允许特定的用户直接绑定到服务器上,这样的话匿名绑定(这是我们到此为止所使用的用户搜索办法)就被禁止了。这可能发生在很大规模的组织中,它想要限制能够从目录中读取信息的用户集合。在这种情况下,标准的Spring Securiry LDAP认证就行不通了,必须使用一种替代策略,通过o.s.s.ldap.authentication.PasswordComparisonAuthenticator实现(BindAuthenticator的兄弟类)。



 PasswordComparisonAuthenticator绑定到LDAP上并查找匹配用户所提供用户名的DN。它接下来会比较用户提供的密码和匹配的LDAP条目中存储的userPassword属性。如果编码后的密码相匹配,用户认证成功,接下来的流程与BindAuthenticator相同。

配置基本的密码对比

配置密码对比认证来替换绑定认证很简单,只需在<ldap-authentication-provider>中添加一个子元素即可,如下:

 

<ldap-authentication-provider server-ref="ldapLocal"
  user-search-filter="(uid={0})" group-search-base="ou=Groups">
  <password-compare/>
</ldap-authentication-provider> 

默认的PasswordComparisonAuthenticator使用LDAP密码编码算法SHA(回忆一下我们在第四章:凭证安全存储中讨论过的SHA-1密码加密算法)。在重启服务之后,你可以使用用户名shapassworduser和密码password尝试登录。

LDAP密码编码和存储

         LDAP支持多种的密码加密算法,从简单文本到单向加密算法(类似于我们在第四章中了解到的基于数据库认证)。最常用的LDAP密码存储格式是SHASHA-1单向加密)和SSHA(使用salt值的单向加密算法)。很多的LDAP实现支持RFC 2307, An Approach for Using

LDAP as a Network Information Service (http://tools.ietf.org/html/rfc2307)定义的其它的密码格式。

         RFC 2307的设计者在密码存储方面做了一项很高明的事情。从目录中的得到的密码当然是按照一定的算法(SHA等)进行加密的,但是它以使用的加密算法作为前缀。这使得LDAP服务器能够很容易支持多种密码编码算法。例如,一个SHA编码的密码在目录中存储如下:

{SHA}5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

         我们可以看到密码存储算法很清楚地进行了标明(使用{SHA}标识),并于密码一起存储。

         SSHA是尝试联合使用SHA-1哈希算法和密码salting,以防止目录攻击。正如我们在第四章中所了解的那样,salt在计算hash之前添加到密码中。当经过hash的密码存储到目录中后,salt值也拼在hash后的密码上。密码以{SSHA}开头,这样LDAP服务器能够知道用户提供的密码需要以不同的方式进行对比。大多数的现代LDAP使用SSHA作为默认的密码存储算法。

密码对比认证的缺点

         现在你了解了一些关于LDAP用户密码并建立了PasswordComparisonAuthenticator,这是请你想一下如果使用sshapassworduser用户以及SSHA格式存储的密码登录会发生什么?试一下——把书放在一边,尝试一下,然后回来。

         你的登录被拒绝了,对不?可是你还能够使用SHA编码密码的用户登录——为什么?当我们使用绑定授权时,密码编码方式和存储并不会影响我们——你觉得这会是为什么呢?

         绑定认证不会受到影响是因为LDAP服务器进行了认证和校验用户密码。在使用密码对比认证的时候,Spring Security LDAP负责将密码编码成目录期望的格式然后与目录进行对比进行认证校验。

         为了安全,密码对比策略并不能真正从目录上读取(基于安全策略,读取目录的密码通常会被拒绝)。作为替代,PasswordComparisonAuthenticator会从用户的目录条目作为根节点进行一个LDAP查找,试图查找与Spring Security编码密码值匹配的密码属性值。所以,当我们以sshapassworduser登录时,PasswordComparisonAuthenticator使用配置的SHA算法对密码进行编码并试图进行简单查找,这个查找失败了,因为目录中的用户密码是以SSHA的格式存储的。

         当我们将PasswordComparisonAuthenticatorhash算法改成使用SSHA会发生什么呢,如下: 

 

<password-compare hash="{ssha}"/>

 重新启动并尝试——它还是不能好用。让我们想一下可能为什么。记住SSHA使用的是salted密码,而salt值是与密码一起存储LDAP目录上的。但是PasswordComparisonAuthenticator编码并不能从LDAP中获取任何信息(这在不允许的绑定的公司中是违背安全策略的)。所以当PasswordComparisonAuthenticator计算hash密码时,它不能确定使用什么salt值。

         总之,PasswordComparisonAuthenticator在特定的环境下很有用(要考虑目录本身的安全),但是它并不像直接绑定认证灵活。

配置UserDetailsContextMapper

         正如我们在前面讲到的,一个o.s.s.ldap.userdetails.UserDetailsContextMapper实例用来匹配用户条目和内存中的UserDetails对象。默认UserDetailsContextMapper的行为与JdbcDaoImpl类似,都是将一定数量的细节信息填充到要返回的UserDetails中——也就是说,除了用户名和密码以外并没有太多的信息。

         但是,LDAP目录可以包括除了用户名、密码和角色以外更多的用户细节信息。Spring Security提供了方法从两个标准的LDAP对象模式——personinetOrgPerson获取更多的用户信息。

明确配置UserDetailsContextMapper

         为了配置一个不同与默认实现的UserDetailsContextMapper,我们只需简单声明希望LdapAuthenticationProvider返回什么类型的LdapUserDetails类即可。security命名空间解析器能够根据要求的LdapUserDetails类型,足够智能地实例化正确的UserDetailsContextMapper

         让我们配置使用inetOrgPerson版本的匹配器。

 

<ldap-authentication-provider server-ref="ldapLocal"
  user-search-filter="(uid={0})" group-search-base="ou=Groups" 
  user-details-class="inetOrgPerson">

 如果你重启应用并尝试使用LDAP用户登录,你会发现没有任何变化。实际上,UserDetailsContextMapper在幕后已经发生了变化,在本例中会根据inetOrgPerson模式从用户目录条目中读取额外的细节信息。

查看其它的用户细节

         作为这节的辅助功能,我们将在JBCP Pets的账号信息页面增加“View LDAP User Profile”区域。我们会用这个页面来阐述更丰富的personinetOrgPerson LDAP模式能提供更多(可选)的信息给使用LDAP的应用。

         添加以下逻辑到AccountController中:

 

@RequestMapping(value="/account/viewLdapUserProfile.
do",method=RequestMethod.GET)
public void showViewLdapUserProfilePage(ModelMap model) {
  final Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  model.addAttribute("user", principal);
  if(principal instanceof LdapUserDetailsImpl) {
    model.addAttribute("isLdapUserDetails", Boolean.TRUE);
  } 
  if(principal instanceof Person) {
    model.addAttribute("isLdapPerson", Boolean.TRUE);
  }  
  if(principal instanceof InetOrgPerson) {
    model.addAttribute("isLdapInetOrgPerson", Boolean.TRUE);
  }  
}

 这个代码将会查询LdapAuthenticationProvider存储在Authentication对象中的UserDetails (principal),并确定是什么类型的LdapUserDetailsImpl。页面的代码则要根据不同的UserDetails类型显示绑定到用户认证信息上的细节,JSP代码如下。这个JSP应该放在WebContent/WEB-INF/views/account/viewLdapUserProfile.jsp

 

<!-- Common Header and Footer Omitted -->
<h1>View Profile</h1>
<p>
  Some information about you, from LDAP:
</p>
<ul>
  <li><strong>Username:</strong> ${user.username}</li>
  <li><strong>DN:</strong> ${user.dn}</li>
  <c:if test="${isLdapPerson}">
    <li><strong>Description:</strong> ${user.description}</li>
    <li><strong>Telephone:</strong> ${user.telephoneNumber}</li>
    <li><strong>Full Name(s):</strong>
    <c:forEach items="${user.cn}" var="cn">
      ${cn}<br />
    </c:forEach>
    </li>
  </c:if>
  <c:if test="${isLdapInetOrgPerson}">
    <li><strong>Email:</strong> ${user.mail}</li>
    <li><strong>Street:</strong> ${user.street}</li>
  </c:if>
</ul>

 我们也可以在WebContent/WEB-INF/views/account/home.jsp加一个链接:

 

<li><a href="viewLdapUserProfile.do">View LDAP User Profile</a></li>

 我们已经增加了另外的两个用户即shapasswordpersonshapasswordinetorgperson,你可以用它们来进行比较可用数据元素的不同。重启系统并查看“View LDAP User Profile”页面的三种不同类型的用户(非personpersoninetOrgPerson)。你会发现,当user-details-class被配置成inetOrgPerson时,尽管要返回的是o.s.s.ldap.userdetails.InetOrgPerson,但是其中的域可能被填充也可能没有填充,这取决与目录条目中可以得到的属性。

         实际上,inetOrgPerson拥有很多的属性远超过我们这个简单页面所提到的。你可以查看所有属性的列表:RFC 2798, Definition of the inetOrgPerson LDAP Object Class (http://tools.ietf.org/html/rfc2798)

         你可能会意识到,没有办法支持条目中指明的而标准模式中没有的属性。标准的UserDetailsContextMappers不支持任意列表的属性,但是可以通过使用user-context-mapper-ref属性指向自定义的UserDetailsContextMapper引用。

使用可代替的密码属性

         在很多场景中,可能会需要使用其它的LDAP属性而不是userPassword进行认证。这可能在公司已经部署完自定义的LDAP模式时发生或不需要进行比较严格的密码管理(可以预见的是,这不是一个好主意,但在现实世界中它就存在)。

         PasswordComparisonAuthenticator也支持对用户的密码与一个其它的LDAP条目属性进行校验,而不是标准的userPassword属性。这很容易配置,我们可以提供一个很简单的例子,使用简单文本的telephoneNumber属性,如下:

 

<ldap-authentication-provider server-ref="ldapLocal"
  user-search-filter="(uid={0})" group-search-base="ou=Groups"
  user-details-class="inetOrgPerson">
  <password-compare hash="plaintext" password-attribute="telephoneNumber"/>
</ldap-authentication-provider>

 我们可以重启服务并使用用户userwithphone和密码(即电话号码)1112223333进行登录。

         当然,这种方式的认证具有我们前面讨论过的PasswordComparisonAuthenticator基础认证的所有风险。但是,万一在LDAP中使用它的时候要注意。

使用LDAP作为UserDetailsService

         需要注意的一件事就是LDAP也可以用作UserDetailsService。要记住的是UserDetailsServiceSpring Security中要启用很多其它的功能,包括remember meOpenID认证功能。

         配置LDAP作为UserDetailsServiceLDAP AuthenticationProvider中是很简单的。就像JDBC UserDetailsService,一个LDAP UserDetailsService作为<http>的兄弟节点进行声明。

 

<ldap-user-service id="ldapUserService" server-ref="ldapLocal" 
  user-search-filter="(uid={0})" group-search-base="ou=Groups"/>

 在功能上,o.s.s.ldap.userdetails.LdapUserDetailsService的配置与LdapAuthenticationProvider的配置基本完全相同,除了没有尝试使用安全实体的用户名绑定LDAP。相反的,<ldap-server>应用提供的凭证信息用来进行用户的查找。

         【如果你想自己使用LDAP认证用户,请避免使用user-details-service-ref(引用了一个LdapUserDetailsService)配置<authentication-provider>的常见错误。】

         就像我们前面提到的那样,LdapUserDetailsService使用<ldap-server>提供的manager-dn来获取自己的信息——这意味着它不会尝试绑定用户到LDAP上,这可能与你期望的行为不一样。LdapUserDetailsService一般用来支持系统的其它组件,如OpenID登录或remember me中,在这里认证已经通过的但是用户的详细信息在认证过程中并没有提供。

注意使用LDAP UserDetailsService时的remember me

         注意的是,如果此时重新启动服务器会失败,并有如下的错误信息:

 

More than one UserDetailsService registered. Please use a specific Id 
reference in <remember-me/> <openid-login/> or <x509 /> elements.

 如果我们回忆一下在第三章:增强用户体验第四章:凭证安全存储中对于remember me功能的介绍,我们就会记得remember me依赖UserDetailsService来查找remember me cookie中的用户名。不幸的是,AbstractRememberMeServices只可能查找一个UserDetailsService获取用户信息。所以,我们使用remember me功能时只能有一个配置的UserDetailsService而不能是两个。这使得使用相同的登录页同时支持LDAP认证和JDBC,并为用户提供remember me功能变得很难实现。调整<remember-me>配置引用某一个UserDetailsService(通过Spring Bean ID)足以明确告诉Spring Security你想做什么。

配置基于内存的remember me服务

         LDAP中另一个关于使用remember me要注意的是——为了给LDAP认证的用户提供remember me功能,你必须(通常会这样)使用基于JDBC持久化的token remember me服务。

         你可能还记得在第三章中讨论的remember me cookie的组成,基于内存的remember me算法(在InMemoryTokenRepositoryImpl)依赖于从UserDetails得到的用户名和密码。在很多场景下,LDAP服务器配置成不允许读取userPassword属性(这就是为什么PasswordComparisonAuthenticator写成那个样子),所以LdapUserDetailsMapper很可能不能为UserDetails对象填充password属性。缺失这个关键的属性会导致创建remember me cookie失败,而且会潜在的影响cookie的安全。

         避免这个问题也很简单——配置位于JDBC中的remember me cookie存储,它只依赖于用户名来校验cookie(我们在第四章已经讨论过)。

集成外部的LDAP服务器

         很可能你在测试完与嵌入式LDAP服务器集成后就要与外部的LDAP 服务器交互了。幸运的是,这是简单,通过建立嵌入式LDAP 服务器的<ldap-server>指令的简单语法就能完成。

         以下的代码就是一个连接在10389端口上的外部LDAP 服务器的示例配置:

 

<ldap-server url="ldap://localhost:10389/dc=jbcppets,dc=com" 
id="ldapLocal"  manager-dn="uid=admin,ou=system" manager-password="secret"/>

 这里的明显区别(除了LDAP URL)就是提供了用户的DN和密码。这个账号(实际上是可选的)应该允许绑定到目录上并且能够进行所有相关用户和组信息的查询。使用这些凭证对LDAP服务器URL的绑定结果就是原来进行安全系统其它的LDAP操作。

         注意很多的LDAP服务器支持SSL加密的LDAPLDAPS)——这无疑也是出于安全的考虑,Spring LDAP也支持。只需在LDAP服务器URL上使用ldaps://开始即可。LDAPS通常运行在636TCP端口。

         注意有很多的商业或非商业的LDAP实现。用于连接、用户绑定、填充GrantedAuthoritys的具体配置完全取决于其提供者和目录的结构。在下一个章节中,我们会讲解一个很通用的LDAP实现,即Microsoft Active Directory

 

  • 大小: 54.1 KB
0
0
分享到:
评论

相关推荐

    Spring Security3.2搭建LDAP认证授权

    2. 配置Spring Security的XML或Java配置,包括安全拦截规则、LDAP设置和Remember-me配置。 3. 编写自定义的`LdapAuthoritiesPopulator`,以处理角色映射。 4. 测试认证和授权流程,确保用户能正确登录,并在下次访问...

    spring-security-ldap-2.0.1

    2. Spring Security LDAP:Spring Security LDAP是Spring Security的一个模块,它允许开发者将应用的安全认证和授权功能与LDAP服务器集成,从而实现基于目录的服务认证。 二、Spring Security LDAP核心概念 1. ...

    spring-security-samples-ldap

    spring security 3 ldap验证方式示例

    Spring Security ldap 1.3.2

    而Spring Security LDAP模块则是Spring Security的一个扩展,它允许开发者利用 Lightweight Directory Access Protocol (LDAP) 进行用户认证和授权。在Spring Security 1.3.2版本中,这个模块为开发者提供了与LDAP...

    SpringSecurity 3配置文件

    在本文中,我们将深入探讨Spring Security 3的配置文件,以及如何理解和使用这些配置来增强应用的安全性。 首先,Spring Security的配置通常位于一个或多个XML文件中,这些文件通过`&lt;beans&gt;`标签定义了安全相关的...

    spring security3 中文版本

    #### 二、Spring Security 命名空间配置 ##### 2.1 命名空间的设计 Spring Security 提供了一个简洁的命名空间,用于简化配置过程。这种设计使得开发者可以使用更少的 XML 配置来实现复杂的安全需求。 ##### 2.2 ...

    spring security3配置和使用实例+教程

    教程文档`教你使用_SpringSecurity_3.0_52页.pdf`会详细指导你如何一步步配置和使用Spring Security。它应该包含了配置文件的示例、如何集成到Spring应用中、如何创建自定义认证逻辑以及如何进行授权设置等内容。...

    springsecurity使用配置详解

    在提供的压缩包`springsecurity配置demo`中,你将找到示例代码和详细说明,这将帮助你更好地理解和实践上述概念。通过学习和实践这些示例,你将能够为自己的Spring应用程序构建强大的安全防护。

    《Spring Security3》第二章第三部分翻译(下)附前两章doc文档

    《Spring Security3》第二章第三部分的翻译下篇主要涵盖了Spring Security的核心概念和技术,这部分内容是深入理解Spring Security架构和实现安全控制的关键。在本章节中,我们将详细探讨以下几个核心知识点: 1. *...

    SpringLdapDemo

    学习SpringSecurity时,看到LDAP认证,不了解LDAP根本无从下手。所以转头学习了一下LDAP,搭建了一个DEMO,仅作记录。 LDAP(Lightweight Directory Access Protocol) 轻量级目录访问协议,LDAP目录以树状的层次结构...

    springSecurity3中文文档

    第二章:springsecurity起步 第三章:增强用户体验 第四章:凭证安全存储 第五章:精确的访问控制 第六章:高级配置和扩展 第七章:访问控制列表(ACL) 第八章:对OpenID开放 第九章:LDAP目录服务 第十章:使用...

    Spring Security3 Demo

    在"SpringSecurity2Demo"这个项目中,我们可以预期看到以下组成部分: 1. **配置文件**: `spring-security.xml`,这是Spring Security的核心配置文件,包含了过滤器链的配置、用户认证源、授权规则等。 2. **控制...

    SpringSecurity.pdf

    Spring Security提供了丰富的认证机制,支持多种认证方式,包括但不限于表单认证、LDAP认证、CAS认证等。认证成功后,用户的身份会被标记为已认证,然后系统根据用户的权限来进行授权,授权是指决定一个已认证的用户...

    Spring Security LDAP 全选管理框架 中文版

    2. **配置LDAP服务器:** 需要在Spring Security的配置文件中指定LDAP服务器的信息,包括主机名、端口、DNS域名等。 3. **定义认证源:** 使用`LdapAuthenticationProvider`来定义认证源,并配置相关的属性,如用户...

    spring-ldap1.3.1

    Spring LDAP很好地融入了Spring生态,可以与其他Spring模块(如Spring JDBC、Spring Security)无缝集成。这使得在处理多种数据存储时,代码风格和事务管理保持一致。 6. "lib"文件夹: 压缩包中的"lib"文件夹很...

    Spring Security 3 中文 chm

    教程部分则会通过实例引导你一步步实现Spring Security的基础和高级功能,帮助你快速上手并熟练掌握。 总的来说,这个资源包是学习Spring Security 3的理想资料,无论你是初学者还是有一定经验的开发者,都能从中...

    Spring+LDAP实现单点登录

    2. **Spring Security**:作为Spring框架的一部分,Spring Security提供了一套强大且高度可配置的安全管理基础设施,支持HTTP安全、基于角色的访问控制、CSRF防护、会话管理等功能。在SSO实现中,Spring Security...

    浅谈Spring Security LDAP简介

    Spring Security LDAP是Spring Security框架中的一部分,提供了对LDAP的支持,使得开发者可以轻松地集成LDAP身份验证和授权机制到自己的项目中。 二、Maven Dependency 要使用Spring Security LDAP,需要在Maven...

    spring security 官方文档

    9. **自定义**:Spring Security非常灵活,允许开发者根据需求自定义大部分组件,如访问决策管理器、权限评估器等,以满足特定业务场景。 10. **与其他Spring框架的集成**:Spring Security与Spring Boot、Spring ...

Global site tag (gtag.js) - Google Analytics