JAVA实现:使用sAMAccountName作为登录名通过LDAP目录库验证
2009-09-08 16:24
841 查看
(转载请注明出处为本博客)
(2-2009至6-2009)要做一套对项目开发、跟踪、管理、多服务器同步备份的系统集成。主要结合svn、apache、tomcat、bugzilla、sendmail、openSSL、LDAP这些开源优秀软件在ubuntu下实现。其中涉及到JAVA EE的WEB开发,EMAIL、NDS应用模块的配置和结合,数据加密,项目管理过程设计,SVN数据的备份与恢复等等。而我和几个teammates主要负责开发一个web应用程序,对svn中各个库的用户权限进行详细管理。
Linux下这些软件的结合是由一位Linux高手用了两个月时间,一步一步的配置起来,间中遇到的各种各样问题,在大家的努力下,终于把整个系统搭建起来。
因为公司原来就已经组建了一个非常完善的LDAP目录库,LDAP目录库,就像一个通信录,里面已经存放了所以公司人员的基本信息(如姓名,邮箱,职位等等)。这里有一个前提:所有的公司员工作为用户都可以登录这个web应用程序,登录后,系统则再根据那些SVN库对于这个用户是否有开放访问权限,如果有,则展现给用户。所以我们可以充分利用这个LDAP目录库,非常方便的管理这个WEB应用程序的使用用户。
现在不谈整个验证过程,就谈谈登录时,如何匹配LDAP目录库的信息,从而通过登录验证。匹配LDAP目录库记录时,要求要提供以下信息:LDAP目录库地址,基准DN,个人的CN,登录密码。如下面的一个例子:
LDAP目录库地址: ldap://10.67.10.2:3268/
基准DN: DC=corp,DC=sb
个人的CN: CN=Xiaopeng Deng,OU=HR,DC=CN,DC=corp,DC=sb
登录密码: 123456
sAMAccountName是个人的CN结点中的一个属性,例如上述的个人的CN的sAMAccountName的值为:xdeng。我命名它为shortname,即短名。在外国非常流行于使用shortname作为个人在公司中的称号,包括用于各种系统的登录。现在这个web应用程序也要使用这个sAMAccountName作为登录名登录。查了JAVA操作LDAP库的包,解决方法还是有的:
1,用户提供了sAMAccountName和密码,想登录系统。
2,首先要使用一个已知个人的CN及其密码,登录到LDAP目录库。登录成功后,这里会返回一个LDAP上下文类:InitialLdapContext。
3,利用这个上下文类中的方法:SearchControls,可以根据搜索条件字符串返回一个枚举类:NamingEnumeration,这时的搜索条件就可以指定sAMAccountName的值为用户输入的shortname。
4,如果搜索返回的枚举类中有值,则可以从这个对象中获取得它的 CN值。没有,则说明不存在这个用户
5,再根据这个CN值,和用户提供的密码,进行LDAP目录库的登录验证匹配过程。
目的其实非常单纯:先用一个已知的CN及其密码通过LDAP目录库验证,然后就可以查找到用户提供的shortname的对应CN是什么,最后就利用这个CN和用户提供的密码验证。最重要就是获得用户shortname的对应CN!
具体的类代码分享出来:(其中部分经过了我老大的修改后,更加完善,老大厉害!)
使用单态模式
代码中的bindDN,bindPassword变量值就是首先知道的CN及其密码,值放在资源文件中。
(2-2009至6-2009)要做一套对项目开发、跟踪、管理、多服务器同步备份的系统集成。主要结合svn、apache、tomcat、bugzilla、sendmail、openSSL、LDAP这些开源优秀软件在ubuntu下实现。其中涉及到JAVA EE的WEB开发,EMAIL、NDS应用模块的配置和结合,数据加密,项目管理过程设计,SVN数据的备份与恢复等等。而我和几个teammates主要负责开发一个web应用程序,对svn中各个库的用户权限进行详细管理。
Linux下这些软件的结合是由一位Linux高手用了两个月时间,一步一步的配置起来,间中遇到的各种各样问题,在大家的努力下,终于把整个系统搭建起来。
因为公司原来就已经组建了一个非常完善的LDAP目录库,LDAP目录库,就像一个通信录,里面已经存放了所以公司人员的基本信息(如姓名,邮箱,职位等等)。这里有一个前提:所有的公司员工作为用户都可以登录这个web应用程序,登录后,系统则再根据那些SVN库对于这个用户是否有开放访问权限,如果有,则展现给用户。所以我们可以充分利用这个LDAP目录库,非常方便的管理这个WEB应用程序的使用用户。
现在不谈整个验证过程,就谈谈登录时,如何匹配LDAP目录库的信息,从而通过登录验证。匹配LDAP目录库记录时,要求要提供以下信息:LDAP目录库地址,基准DN,个人的CN,登录密码。如下面的一个例子:
LDAP目录库地址: ldap://10.67.10.2:3268/
基准DN: DC=corp,DC=sb
个人的CN: CN=Xiaopeng Deng,OU=HR,DC=CN,DC=corp,DC=sb
登录密码: 123456
sAMAccountName是个人的CN结点中的一个属性,例如上述的个人的CN的sAMAccountName的值为:xdeng。我命名它为shortname,即短名。在外国非常流行于使用shortname作为个人在公司中的称号,包括用于各种系统的登录。现在这个web应用程序也要使用这个sAMAccountName作为登录名登录。查了JAVA操作LDAP库的包,解决方法还是有的:
1,用户提供了sAMAccountName和密码,想登录系统。
2,首先要使用一个已知个人的CN及其密码,登录到LDAP目录库。登录成功后,这里会返回一个LDAP上下文类:InitialLdapContext。
3,利用这个上下文类中的方法:SearchControls,可以根据搜索条件字符串返回一个枚举类:NamingEnumeration,这时的搜索条件就可以指定sAMAccountName的值为用户输入的shortname。
4,如果搜索返回的枚举类中有值,则可以从这个对象中获取得它的 CN值。没有,则说明不存在这个用户
5,再根据这个CN值,和用户提供的密码,进行LDAP目录库的登录验证匹配过程。
目的其实非常单纯:先用一个已知的CN及其密码通过LDAP目录库验证,然后就可以查找到用户提供的shortname的对应CN是什么,最后就利用这个CN和用户提供的密码验证。最重要就是获得用户shortname的对应CN!
具体的类代码分享出来:(其中部分经过了我老大的修改后,更加完善,老大厉害!)
使用单态模式
代码中的bindDN,bindPassword变量值就是首先知道的CN及其密码,值放在资源文件中。
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.util.Hashtable; import java.util.Properties; import javax.naming.Context; import javax.naming.NameClassPair; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import javax.naming.ldap.SortControl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.util.Constant; /** * LDAP Connector seems like JDBC, supposed to interface with AD. * * Use singleton pattern to prevent multi-instances. * */ public class LDAPConnector { /** Logger for this class and subclasses */ protected final Log log = LogFactory.getLog(getClass()); private static LDAPConnector instance; private String url; private String baseDN; private String bindDN; private String bindPassword; private final Hashtable<String, String> env = new Hashtable<String, String>(); private final Control[] sortConnCtls = new SortControl[1]; { try { sortConnCtls[0] = new SortControl("sAMAccountName", Control.CRITICAL); } catch (IOException ex) { } } private LDAPConnector() { try { URL fileUrl = getClass().getClassLoader().getResource(Constant.FILE_LDAP_CONFIG); File resource = new File(fileUrl.getFile()); Properties properties = new Properties(); properties.load(new FileInputStream(resource)); url = properties.getProperty("url"); baseDN = properties.getProperty("baseDN"); bindDN = properties.getProperty("bindDN"); bindPassword = properties.getProperty("bindPassword"); // set up environment for creating initial context env.put(Context.PROVIDER_URL, url + baseDN); env.put(Context.SECURITY_PRINCIPAL, bindDN); env.put(Context.SECURITY_CREDENTIALS, bindPassword); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put("java.naming.batchsize", "50"); env.put("com.sun.jndi.ldap.connect.timeout", "3000"); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put("com.sun.jndi.ldap.connect.pool", "true"); // the following pool parameters doesn't work // must setup as java init parameters env.put("com.sun.jndi.ldap.connect.pool.maxsize", "3"); env.put("com.sun.jndi.ldap.connect.pool.prefsize", "1"); env.put("com.sun.jndi.ldap.connect.pool.timeout", "300000"); env.put("com.sun.jndi.ldap.connect.pool.initsize", "1"); env.put("com.sun.jndi.ldap.connect.pool.authentication", "simple"); } catch (Exception e) { // ignore error e.printStackTrace(); } } public static LDAPConnector getInstance() { if (instance == null) instance = new LDAPConnector(); return instance; } public boolean validateUser(String username, String password) { boolean passed = false; LdapContext dirContext = null; try { // create initial context dirContext = new InitialLdapContext(env, sortConnCtls); dirContext.setRequestControls(sortConnCtls); SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(sAMAccountName=" + username + ")"; NamingEnumeration<?> answer = dirContext.search("", filter, controls); String userDN = null; while (answer.hasMore()) { userDN = ((NameClassPair) answer.nextElement()).getName(); } // set up environment for creating initial context Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.PROVIDER_URL, url + baseDN); env.put(Context.SECURITY_PRINCIPAL, userDN + "," + baseDN); env.put(Context.SECURITY_CREDENTIALS, password); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put("com.sun.jndi.ldap.connect.timeout", "1000"); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // create initial context DirContext context = new InitialDirContext(env); passed = true; context.close(); } catch (NamingException e) { // ignore error // e.printStackTrace(); } finally { if (dirContext != null) { try { dirContext.close(); } catch (NamingException e) { e.printStackTrace(); } } } return passed; } }
相关文章推荐
- 在java程序中,使用sAMAccountName作为登录名通过LDAP目录库验证
- ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
- 使用Delphi 通过WebServices 要想实现到.Net 或者是Java的WebServices 头验证.
- ASP.NET jQuery 食谱11 (通过使用jQuery validation插件简单实现用户登录页面验证功能)
- ASP.NET jQuery 实例11 通过使用jQuery validation插件简单实现用户登录页面验证功能
- 通过Ajax实现不显示登录框的IIS-Windows集成身份验证登录
- JAVA邮件发送的简单实现,使用javamail通过smtp协议发信
- session和cookie的使用方法、区别,和分别实现验证登录状态
- 使用SSM(Spring+SpringMVC+Mybatis)框架搭建服务器实现登录验证
- symfony使用security实现验证登录
- 使用truelicense实现用于JAVA工程license机制(包括license生成和验证)
- 使用JAVA通过ARP欺骗类似P2P终结者实现数据封包监听
- PHP通过session id 实现session共享和登录验证-android开发非常重要
- 通过代理类实现java连接数据库(使用dao层操作数据)实例分享
- 本地JAVA开发页面使用AAD验证登录
- java中使用session监听实现同帐号登录限制、登录人数限制
- 使用java,tomcat,mysql实现登录功能
- 快速开发android应用2-使用TextInputLayout实现用户登录及验证
- 使用Ajax实现登录验证
- 通过discuzX2.5 社区与java 的单点登录的实现(测试)