分享

使用Apache Shiro进行身份认证

 wayne_liberary 2014-08-06
通常在根据LDAP进行身份验证时会采取以下三种方法:

1、利用一个LDAP用户的用户名和密码绑定到LDAP服务器。

2、在LDAP中检索一个用户的条目,然后将提供的密码和检索到的LDAP记录中的密码属性相比较。

3、“两次绑定”验证方法。

基于LDAP进行身份验证,最好也是最通用的方法就是 “两次绑定”。这种方法的步骤以及优点可参看我的另一篇博客:基于LDAP进行验证-方法和问题

当前Shiro只支持了第一种方法,即使用用户名和密码到LDAP服务器中进行绑定来判断合法性。

我自己写了一个认证类,实现了“两次绑定”验证。同时解决了目前做LDAP认证时没有区分错误情况,返回的错误提示信息不够准确的问题。

配置信息:

  1. [main]  
  2. ldapRealm = main.java.name.peter.shiro.realm.ldap.LdapAuthenticator  
  3. ldapRealm.rootDN = dc=example,dc=com  
  4. ldapRealm.contextFactory.url = ldap://localhost:389  
  5. ldapRealm.contextFactory.systemUsername = cn=Manager,dc=example,dc=com  
  6. ldapRealm.contextFactory.systemPassword = secret  

认证类:
  1. /*** 
  2.  * 基于Ldap进行身份认证,二次绑定方式. 
  3.  *  
  4.  * @author wanghao 
  5.  *  
  6.  */  
  7. public class LdapAuthenticator extends JndiLdapRealm {  
  8.   
  9.     private static final Logger log = LoggerFactory  
  10.             .getLogger(LdapAuthenticator.class);  
  11.     private String rootDN;  
  12.   
  13.     public LdapAuthenticator() {  
  14.         super();  
  15.     }  
  16.   
  17.     public String getRootDN() {  
  18.         return rootDN;  
  19.     }  
  20.   
  21.     public void setRootDN(String rootDN) {  
  22.         this.rootDN = rootDN;  
  23.     }  
  24.   
  25.     @Override  
  26.     /*** 
  27.      * 认证 
  28.      */  
  29.     protected AuthenticationInfo doGetAuthenticationInfo(  
  30.             AuthenticationToken token) throws AuthenticationException {  
  31.         AuthenticationInfo info;  
  32.         try {  
  33.             info = queryForAuthenticationInfo(token, getContextFactory());  
  34.         } catch (AuthenticationNotSupportedException e) {  
  35.             String msg = "Unsupported configured authentication mechanism";  
  36.             throw new UnsupportedAuthenticationMechanismException(msg, e);  
  37.         } catch (javax.naming.AuthenticationException e) {  
  38.             String msg = "LDAP authentication failed.";  
  39.             throw new AuthenticationException(msg, e);  
  40.         } catch (NamingException e) {  
  41.             String msg = "LDAP naming error while attempting to authenticate user.";  
  42.             throw new AuthenticationException(msg, e);  
  43.         } catch (UnknownAccountException e) {  
  44.             String msg = "UnknownAccountException";  
  45.             throw new UnknownAccountException(msg, e);  
  46.         } catch (IncorrectCredentialsException e) {  
  47.             String msg = "IncorrectCredentialsException";  
  48.             throw new IncorrectCredentialsException(msg, e);  
  49.         }  
  50.   
  51.         return info;  
  52.     }  
  53.       
  54.     @Override  
  55.     protected AuthenticationInfo queryForAuthenticationInfo(  
  56.             AuthenticationToken token, LdapContextFactory ldapContextFactory)  
  57.             throws NamingException {  
  58.   
  59.         Object principal = token.getPrincipal();  
  60.         Object credentials = token.getCredentials();  
  61.   
  62.         LdapContext systemCtx = null;  
  63.         LdapContext ctx = null;  
  64.         try {  
  65.             systemCtx = ldapContextFactory.getSystemLdapContext();  
  66.   
  67.             SearchControls constraints = new SearchControls();  
  68.             constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);  
  69.             NamingEnumeration results = systemCtx.search(rootDN, "cn="  
  70.                     + principal, constraints);  
  71.             if (results != null && !results.hasMore()) {  
  72.                 throw new UnknownAccountException();  
  73.             } else {  
  74.                 while (results.hasMore()) {  
  75.                     SearchResult si = (SearchResult) results.next();  
  76.                     principal = si.getName() + "," + rootDN;  
  77.                 }  
  78.                 log.info("DN="+principal);  
  79.                 try {  
  80.                     ctx = ldapContextFactory.getLdapContext(principal,  
  81.                             credentials);  
  82.                 } catch (NamingException e) {  
  83.                     throw new IncorrectCredentialsException();  
  84.                 }  
  85.                 return createAuthenticationInfo(token, principal, credentials,  
  86.                         ctx);  
  87.             }  
  88.         } finally {  
  89.             LdapUtils.closeContext(systemCtx);  
  90.             LdapUtils.closeContext(ctx);  
  91.         }  
  92.     }  
  93. }  



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多