Spring Security进阶——集成LDAP认证

如果对于这系列文章有疑问,可以先阅读以下链接内容(含Demo及源码下载): 
Spring Security入门篇——搭建简易权限框架: http://www.javali.org/archive/getting-start-spring-security.html  

Spring Security入门篇——集成DB认证: http://www.javali.org/archive/getting-start-spring-security-integrate-db.html  

Spring security进阶——扩展UserDetails: http://www.javali.org/archive/spring-security-advanced-extend-userdetails.html  

Spring security进阶——资源汉化(i18n): http://www.javali.org/archive/spring-security-advanced-i18n.html  


进入主题前,需要从以上链接中下载Demo工程,Spring Security提供了良好的LDAP扩展方式,基于简单的配置即可集成到你的应用里 
在simpleDemo项目pom.xml的基础上引入: 
Java代码   收藏代码
  1.   
  2.  org.springframework.security  
  3.  spring-security-ldap  
  4.  3.0.5.RELEASE  
  5.  jar  
  6.  compile  
  7.   


但是集成方式取决于LDAP存储的数据及业务系统需求,需要分两种情况考虑: 

1,LDAP服务器中存有帐号信息和角色信息 

2,LDAP服务器只存了帐号信息 

大多场合都属于后者,因为角色是由业务系统需求决定的,而LDAP在企业仅作为用户信息存储的一种方案,下面就这两种情况来看SS是怎样集成LDAP认证的 

第一种情况: 
LDAP上已经存有用户帐号及角色信息,我们只需要根据SS提供的对外接口,配置上相应的参数就行了,用户密码验证,获取角色等交给SS的LDAP扩展模块自己完成,将 security_ldap1  

覆盖SimpleDemo中的security.xml配置文件即可,建议用 Apache Directory Studio 


了解LDAP数据的内部结构后再替换红色字体部分 
Java代码   收藏代码
  1.  id="myLdap"  
  2.  port="389"  
  3.  url="ldap://ldap.javali.org:389/dc=javali,dc=org"   #LDAP服务地址  
  4.  manager-dn="[email protected]"     #提供一个有权限访问ldap服务的帐号  
  5.  manager-password="*******" />  
  6.    
  7.  
  8.  server-ref="myLdap"  
  9.  user-search-filter="(accountName={0})"     #ldap目录中存帐号名的节点名称  
  10.  user-search-base="OU=Users,OU=DEPARTMENT"  #用户查找base  
  11.  group-search-base="OU=Groups"  
  12.  group-role-attribute="cn"  
  13.  group-search-filter="(member={0})"      #用户所属角色的节点名称  
  14.  role-prefix="ROLE_">  
  15.    
  16.    


第二种情况: 

比第一种情况复杂很多,既然角色由业务系统需求决定,角色信息就保存在业务系统的数据库;处理流程应该是:LDAP负责密码认证,然后在SS- 

LDAP基础上做扩展,从DB中加载用户角色,思路是正确的,但如何扩展,如何实现,困扰了我很长时间;最后多亏了snowolf的鼎力支持(暗自庆幸身 

边有spring大牛真好) 

我们在阅读ss集成ldap源码时发现了DefaultLdapAuthoritiesPopulator类,它有一个方法签名 

Java代码   收藏代码
  1. protected Set getAdditionalRoles(DirContextOperations user, String username)  
  2.   
  3. 我想你看到方法名就应该知道它的作用了,我们就可以写一个类继承DefaultLdapAuthoritiesPopulator,在getAdditionalRoles方法里加上从数据库获取username的角色列表代码就完事了,代码如下  
  4. public class MyLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator {  
  5.  public MyLdapAuthoritiesPopulator(ContextSource contextSource,  
  6.  String groupSearchBase) {  
  7.  super(contextSource, groupSearchBase);  
  8.  }  
  9.  protected Set getAdditionalRoles(  
  10.  DirContextOperations user, String username) {  
  11.  // 授权集合  
  12.  Set authorites = new HashSet();  
  13.  // 根据username读取用户信息  
  14.   
  15.  //TODO 根据用户信息从DB取得用户角色列表  
  16.   //将角色添加到集合里即可  
  17.  GrantedAuthority authority = new GrantedAuthorityImpl("");  
  18.  authorites.add(authority);  
  19.  return authorites;  
  20.  }  
  21. }  


此种场景只能采用Bean的配置方式 : security_ldap2  
Java代码   收藏代码
  1.  id="contextSource"  
  2.  class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">  
  3.  
  4.  value="ldap://ldap.javali.org:389/dc=javali,dc=org" />  
  5.  
  6.  name="userDn"  
  7.  value="[email protected]" />  
  8.  
  9.  name="password"  
  10.  value="******" />  
  11.    
  12.  
  13.  id="ldapAuthProvider"  
  14.  class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">  
  15.    
  16.  
  17.  class="org.springframework.security.ldap.authentication.BindAuthenticator">  
  18.  
  19.  ref="contextSource" />  
  20.  
  21.  name="userSearch">  
  22.  
  23.  class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">  
  24.  
  25.  value="dc=javali,dc=org" />  
  26.  
  27.  value="(sAMAccountName={0})" />  
  28.  
  29.  ref="contextSource" />  
  30.    
  31.    
  32.    
  33.    
  34.    
  35.  
  36.  id="ldapAuthoritiesPopulator"  
  37.  class="org.javali.security.ext.MyLdapAuthoritiesPopulator">  
  38.  
  39.  ref="contextSource" />  
  40.  
  41.  value="ou=Groups,dc=javali,dc=org" />  
  42.    
  43.    
  44.  
  45.  name="userDetailsContextMapper">  
  46.  
  47.  id="ldapUserDetailsMapper"  
  48.  class="org.springframework.security.ldap.userdetails.LdapUserDetailsMapper">  
  49.  
  50.  name="rolePrefix"  
  51.  value="ROLE_" />  
  52.  
  53.  name="convertToUpperCase"  
  54.  value="true" />  
  55.    
  56.    
  57.    
  58.    
  59.  
  60.  ref="ldapAuthProvider">  
  61.    
  62.    


在配置 BindAuthenticator类时查询用户可有两种方式(可参见它的父类AbstractLdapAuthenticator),一种是 

userDnFormat,另一种是LdapUserSearch,我们采用的是第二种,使用第一种配置的时候发现它只能查找当前userDn目录下用 

户,如果有用户在更深层次就没法做到了,LdapUserSearch可以支持基于目录模糊匹配的查询方式,更强大,至少满足了我的ldap用户查询 

你可能感兴趣的:(java--安全,LDAP,Ldap,ldap)