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

《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-security-samples-ldap

    spring security 3 ldap验证方式示例

    Spring Security3.2搭建LDAP认证授权

    进阶-使用Spring Security3.2搭建LDAP认证授权和Remember-me

    spring-security-ldap-2.0.1

    spring-security-ldap-2.0.1

    springSecurity3中文文档

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

    Spring Security ldap 1.3.2

    spring-security-ldap-1.3.2

    SpringLdapDemo

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

    Spring Security

    Spring Security是什么? 历史 发布版本号 Getting Spring Security Spring Security 4.1新特性 Java 配置提升 Web应用程序安全性提升 授权改进 密码模块的改进 测试的改进 一般的改进 样品和指南 (Start Here) Java ...

    spring security 参考手册中文版

    第二部分 架构与实现 73 9.技术概述 73 9.1运行环境 73 9.2核心组件 74 9.2.1 SecurityContextHolder,SecurityContext和认证对象 74 获取有关当前用户的信息 75 9.2.2 UserDetailsService 75 9.2.3授予权力 77 ...

    Spring Security-3.0.1中文官方文档(翻译版)

    Spring Security-3.0.1 中文官方文档(翻译版) 这次发布的Spring Security-3.0.1 是一个bug fix 版,主要是对3.0 中存在的一些问题进 行修 正。文档中没有添加新功能的介绍,但是将之前拼写错误的一些类名进行...

    最详细Spring Security学习资料(源码)

    身份验证:Spring Security支持多种身份验证方式,包括基本认证、表单登录、LDAP认证、OAuth等,同时也支持自定义的认证方式。 授权:Spring Security提供了细粒度的授权机制,可以根据角色、权限进行访问控制。...

    spring security 4 需要 jar 包

    spring security4 下载地址 http://repo.spring.io/snapshot/org/springframework/security/spring-security/4.0.0.CI-SNAPSHOT/ 所需要 jar 包 apacheds-core-1.5.5.jar aspectjrt-1.6.10.BUILD-20100810.234950-5...

    浅谈Spring Security LDAP简介

    主要介绍了浅谈Spring Security LDAP简介,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    SpringSecurity 3.0.1.RELEASE.CHM

    2. Security命名空间配置 2.1. 介绍 2.1.1. 命名空间的设计 2.2. 开始使用安全命名空间配置 2.2.1. 配置web.xml 2.2.2. 最小 配置 2.2.2.1. auto-config包含了什么? 2.2.2.2. 表单和基本登录选项 2.2.3. ...

    spring security3.2.0

    Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。 Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发的企业...

    SpringSecurity初体验之手动配置用户名密码

    此文章是记录博主在学习springsecurity时的笔记 第一步 创建一个SpringBoot工程,勾选上需要的依赖。 第二步 创建一个名为securityconfig的配置类,该类基础了父类WebSecurityConfigurerAdapter(提供用于创建...

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

    spring 的权限管理框架 中文参考手册 单点登录,LDAP等 详细的介绍了一个权限的分配,不用自己在写过多的程序代码实现权限系统了

    Spring Security 中文教程.pdf

    2. Security命名空间配置 2.1. 介绍 2.1.1. 命名空间的设计 2.2. 开始使用安全命名空间配置 2.2.1. 配置web.xml 2.2.2. 最小 &lt;http&gt; 配置 2.2.2.1. auto-config 包含了什么? 2.2.2.2. 表单和基本登录...

    spring-security Spring Security-3.0.1 中文官方文档

    spring-security-ldap-3.1.4.RELEASE spring-security-openid-3.1.4.RELEASE spring-security-remoting-3.1.4.RELEASE spring-security-taglibs-3.1.4.RELEASE spring-security-web-3.1.4.RELEASE 这些jar包都是通过...

    springboot-oauth2-ldap-example:Belajar Spring Security OAuth2 + JWT + LDAP

    LDAP的安全性Oauth2请求令牌curl -X POST \ ' ...

    springboot-ldap:该项目的目标是创建一个简单的Spring-Boot REST API(称为简单服务),并使用Spring Security LDAP模块对其进行保护。

    该项目的目标是创建一个简单的 REST API(称为simple-service ,并使用Spring Security LDAP模块对其进行Spring Security LDAP 。 应用 简单服务 Spring Boot Java Web应用程序公开了两个端点: GET /api/public ...

Global site tag (gtag.js) - Google Analytics