LDAP作为一种普遍使用的认证服务,可以通过模拟登录的方式来监测服务的可用性。今天写了一个服务来轮询模拟LDAP登录,下面是主要的代码。
LDAP的原理是先用一个admin用户去认证,认证通过后,使用应登录的用户的用户名及密码去登录。
1.常量设置
public class Constants { /** * LDAP服务端地址URL(端口默认389) */ public static final String ldapURL= "ldap://xxx.xxx.xxx.xxx/"; /** * LDAP根 */ public static final String ldapBasedn= "ou=ldaptest,dc=ldaptest,dc=com"; /** * LDAP登陆账号(注:特殊字符\需要进行转义) */ public static final String ldapPrincipal= "ldapadmin"; /** * LDAP登陆密码 */ public static final String ldapCredentials= "ldappassword"; /** * <B>LDAP查询Filter <br/>#arg在代码中可替换为实际查找用户的用户账号<b/> */ public static final String ldapFilter= "(&(objectClass=user)(sAMAccountName=#arg))"; }2.LDAPAuthentication
package com.system.ldap; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; public class LDAPAuthentication implements Runnable { private final String BASEDN = Constants.ldapBasedn; private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; private LdapContext ctx = null; private final Control[] connCtls = null; //private Log log = null; public void LDAP_connect(){ Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY); env.put(Context.PROVIDER_URL, Constants.ldapURL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, Constants.ldapPrincipal); env.put(Context.SECURITY_CREDENTIALS, Constants.ldapCredentials); try { ctx = new InitialLdapContext(env, connCtls); wirte("认证LDAP服务器(" + Constants.ldapURL + ")成功!"); } catch (javax.naming.AuthenticationException e) { wirte("认证LDAP服务器(" + Constants.ldapURL + ")失败,原因:"+e.toString()); //throw new Exception(); } catch (Exception e) { wirte("认证LDAP服务器(" + Constants.ldapURL + ")失败,原因 :"+e.toString()); } } public static void wirte(String msg){ FileWriter fileWriter; try { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); fileWriter = new FileWriter("D:\\log\\ldap.log",true); String s = new String( "["+sf.format(new Date())+"]"+msg); fileWriter.write("\r\n"); fileWriter.write(s); fileWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private String getUserDN(String uid) { try { String userDN = ""; SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // 查找用户DN NamingEnumeration<SearchResult> en = ctx.search(BASEDN, Constants.ldapFilter.replace("#arg", uid), constraints); while (en != null && en.hasMoreElements()) { Object obj = en.nextElement(); if (obj instanceof SearchResult) { SearchResult si = (SearchResult) obj; userDN += si.getName(); userDN += "," + BASEDN; System.out.println(userDN); wirte("查找到用户" + uid + "的DN信息:" + userDN); } else { } } return userDN; } catch (NamingException e) { wirte("查找用户DN时错误!"); wirte("原因:" + e); return null; } catch (Exception e1) { return null; } } public boolean authenricate(String UID, String password) { //是否成功 boolean valide = false; try { //连接 LDAP_connect(); String userDN = getUserDN(UID); if (userDN != null && userDN != "") { // 如果需要加密SHA-1 // password = SHA1.shaBase64(password); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(connCtls); System.out.println(userDN + " 验证通过"); wirte("LDAP用户验证成功!"); valide = true; } else { wirte("未找到" + UID + "用户信息!"); valide = false; } } catch (NamingException e) { wirte("用户信息认证失败!password:" + password); valide = false; } catch (Exception e) { //创建连接失败 valide = false; } finally { // 关闭连接 closeLdapContext(); wirte("close ldap connection"); } return valide; } private void closeLdapContext() { if (ctx != null) { try { ctx.close(); } catch (NamingException e) { wirte("关闭LDAP连接错误,错误原因:"+e); } } } @Override public void run() { // TODO Auto-generated method stub while (true) { try { Thread.sleep(1000); LDAPAuthentication ldap = new LDAPAuthentication(); if (ldap.authenricate("ldapuser", "ldappassword") == true) { System.out.println("该用户认证成功"); wirte("该用户认证成功"); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }3.测试类
使用线程轮询的方式不停地调用认证方法
public class TestLDAP { /** * @param args */ public static void main(String[] args) { LDAPAuthentication Authentication=new LDAPAuthentication(); Thread t1 =new Thread(Authentication); t1.start(); } }4.效果
线程每轮询一次打印一次日志到文件,可以通过日志跟踪认证服务的正常状态。
5.扩展阅读
1) LDAP
http://baike.baidu.com/link?url=e59cBqJmOebBv1FnOUnDFDjAyIoLlmP2Gpg1npNF0b9FaoVO3YgAUppILHp7CPqQdDYC4w33DXxe_yIboMjb5_
2) LDAP概念和原理
http://blog.sina.com.cn/s/blog_6151984a0100ey3z.html
3)LDAP认证基本原理
http://www.edu.cn/sfrz_9956/20120608/t20120608_788018_1.shtml