ACEGI结合LDAP进行统一用户管理

用acegi进行用户登陆和权限判断已有好几个项目的经验了,但是用户密码和权限信息都是存储在数据库里面的,各套系统之间的用户数据彼此都互相独立,这个系统一套用户名密码,那个系统则是另一套,每个用户要同时记住好几个密码,比较麻烦。但是现在的发展趋势都是用LDAP对用户进行统一管理,即在LDAP服务器中进行认证管理,在业务系统里进行授权管理。
这样子,只要各业务系统都练到这一个LDAP服务器上,大家的账号和密码就都是统一的。

以下是acegi与Windows AD进行结合,实现用户统一管理的例子。

实现的思路是,在LDAP进行用户认证,在数据库中进行权限鉴别。

acegi也有针对LDAP进行认证和鉴权的全部代码和推荐配置,但是比较单纯,要么是全部数据库,要么是全部LDAP,对于LDAP+DB,还没有看到网上有例子,只有一个台湾的家伙,还觉得满保密,不想公开他的代码。

Windows AD,就是Windows Active Directory,是微软的域控制器,与windows操作系统进行了集成,支持LDAP协议。

1、将daoAuthenticationProvider换成ldapAuthenticationProvider
Java代码   收藏代码
  1. <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">  
  2.         <property name="providers">  
  3.             <list>  
  4.                 <ref local="ldapAuthenticationProvider"/>  
  5.             </list>  
  6.         </property>  
  7.         <property name="sessionController">  
  8.             <ref bean="concurrentSessionController"/>  
  9.         </property>  
  10.     </bean>  

2、添加ldapAuthenticationProvider的bean定义:
Java代码   收藏代码
  1. <!--  
  2.          LDAP+DB进行登陆判断  
  3.          LDAP中进行用户名认证(authenticator)  
  4.          DB中进行权限判断(daoPopulator)  
  5.      -->  
  6. <bean id="ldapAuthenticationProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">  
  7.         <constructor-arg><ref local="authenticator"/></constructor-arg>  
  8.         <constructor-arg><ref local="daoPopulator"/></constructor-arg>  
  9.         <property name="userCache" ref="userCache"/>  
  10. </bean>  

3、添加authenticator的bean定义
Java代码   收藏代码
  1. <!--  
  2.          在LDAP Server中判断用户和密码的有效性  
  3.         initialDirContextFactory:LDAP上下文环境  
  4.         userDnPatterns:用户匹配模式,其中sAMAccountName是AD中用户名的字段名称  
  5.      -->  
  6. <bean id="authenticator" class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">  
  7.         <constructor-arg><ref local="initialDirContextFactory"/></constructor-arg>  
  8.         <property name="userDnPatterns">  
  9.             <list>  
  10.                 <value>sAMAccountName={0},ou=BroadText_SH,DC=broadtext,DC=local</value>  
  11.             </list>  
  12.         </property>  
  13.         <property name="userSearch"><ref local="userSearch"/></property>  
  14. </bean>  

其中userDnPatterns是根据不同的LDAP服务有着不同的配置,sAMAccountName是AD中存储用户账号的字段名称,后面那一串是账号路径的一部分。
4、编写自己的DaoAuthoritiesPopulator,从数据库中查询权限,这里有两个参数:数据源和查询SQL,数据源可以直接利用已经定义的dataSource,查询SQL就是以前在jdbcDaoImpl中用过的authoritiesByUsernameQuery。类中的代码如下(省去了dataSource和authoritiesByUsernameQuery的setter和getter):
Java代码   收藏代码
  1. private static final Log logger = LogFactory.getLog(DaoAuthoritiesPopulator.class);  
  2.     protected MappingSqlQuery authoritiesByUsernameMapping;  
  3.     private String authoritiesByUsernameQuery;  
  4.     private String rolePrefix = "";  
  5.     private DataSource dataSource;   
  6.     /* (non-Javadoc) 
  7.      * @see org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator#getGrantedAuthorities(org.acegisecurity.userdetails.ldap.LdapUserDetails) 
  8.      */  
  9.     public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails user){  
  10.         this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource());  
  11.         List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername());  
  12.           
  13.         if (dbAuths.size() == 0) {  
  14.             throw new PermissionNotEnoughException("User has no GrantedAuthority");  
  15.         }  
  16.   
  17.         GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]);  
  18.   
  19.         if (logger.isDebugEnabled()) {  
  20.             logger.debug("Getting authorities for user " + user.getUsername());  
  21.             logger.debug("授权成功 :" + user.getUsername());  
  22.         }  
  23.         return arrayAuths;  
  24.     }  
  25.      /** 
  26.      * Query object to look up a user's authorities. 
  27.      */  
  28.     protected class AuthoritiesByUsernameMapping extends MappingSqlQuery {  
  29.         protected AuthoritiesByUsernameMapping(DataSource ds) {  
  30.             super(ds, authoritiesByUsernameQuery);  
  31.             declareParameter(new SqlParameter(Types.VARCHAR));  
  32.             compile();  
  33.         }  
  34.   
  35.         protected Object mapRow(ResultSet rs, int rownum)  
  36.             throws SQLException {  
  37.             String roleName = rolePrefix + rs.getString(2);  
  38.             GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);  
  39.   
  40.             return authority;  
  41.         }  
  42.     }  

bean定义XML文件如下:
Java代码   收藏代码
  1. <!--  
  2.          从数据库中获取权限  
  3.         dataSource:数据源  
  4.         authoritiesByUsernameQuery:根据用户名查询权限的sql   
  5.      -->  
  6. <bean id="daoPopulator" class="com.broadtext.eim.security.ldap.DaoAuthoritiesPopulator">  
  7.         <property name="dataSource" ref="dataSource"/>  
  8.         <property name="authoritiesByUsernameQuery">  
  9.             <value>select u.username,p.name from sys_user u,sys_role r,sys_permission p,sys_user_role ur,sys_role_permis rp where u.id=ur.user_id and r.id=ur.role_id and p.id=rp.permission_id and  
  10.                 r.id=rp.role_id and p.open_flag='1' and u.username=?</value>  
  11.         </property>  
  12. </bean>  

5、添加LDAP服务器上下文的bean配置:
Java代码   收藏代码
  1. <!--  
  2.        LDAP Server的配置信息  
  3.         构造函数的参数:LDAP服务器地址和端口  
  4.        managerDn:管理员账号在LDAP中的地址  
  5.        managerPassword:管理员密码  
  6.      -->  
  7. <bean id="initialDirContextFactory" class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">  
  8.         <constructor-arg value="ldap://你的LDAP服务器地址:端口"/>  
  9.         <property name="managerDn"><value>yourAdministratorName</value></property>  
  10.         <property name="managerPassword"><value>yourAdministratorPassword</value></property>  
  11. </bean>  

这样定义以后,大概相当于指定了进行用户认证的数据库schema。

在这里,推荐一个LDAP的浏览工具,叫LDAP Browser,下载地址是 http://file1.softsea.net/30190/ldapbrowser25ce.zip,可以用这个工具来判断你所拿到的上面三个参数的值是否正确。
6、添加userSearch的bean定义:
Java代码   收藏代码
  1. <!--  
  2.        在LDAP服务器校验账号的时候,定义搜索账号的规则  
  3.      -->  
  4. <bean id="userSearch" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">  
  5.         <constructor-arg>  
  6.             <value>ou=BroadText_SH,DC=broadtext,DC=local</value>  
  7.         </constructor-arg>  
  8.         <constructor-arg>  
  9.             <value>(sAMAccountName={0})</value>  
  10.         </constructor-arg>  
  11.         <constructor-arg>  
  12.             <ref local="initialDirContextFactory"/>  
  13.         </constructor-arg>              
  14.         <property name="searchSubtree">  
  15.             <value>true</value>  
  16.         </property>              
  17. </bean>  


第一个构造参数表示搜索路径(指定了用户认证的数据表),第二个构造参数表示用怎么的查询条件去搜索,第三个构造参数是要搜索的上下文环境(指定了用户认证的数据库schema),,属性searchSubtree为true表示可以在子节点中进行搜索。

大致配置就是这些了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值