LDAP总结

简介

Ldap是一个轻量级访问目录。

具有很强大的查询(读)的功能,适合进行大量数据的检索。

写方面就慢的多,适合读不适合写。

常用字段

含义
oorganization(组织-公司)
ouorganization unit(组织单元/部门)
ccountryName(国家)
dcdomainComponent(域名组件)
snsuer name(真实名称)
cncommon name(常用名称)
dndistinguished name(专有名称)

服务端

问题

       如果数据库选BDB一直启动不了的话,卸载重新安装,选MDB

       slapd -d 1 -f

       run文件夹下的run.cmd

       Win+R->services.msc->OpenLDAP Service设为手动

配置LDAP

       找到安装路径,找到slapd.conf文件

       将dc修改为任意值

suffix		"dc=micmiu,dc=com"
rootdn		"cn=test,dc=micmiu,dc=com"

       C:\Windows\System32\drivers\etc\hosts:在最后添加localhost micmiu.com

导入数据

  • 在安装路径新建文件,后缀名为ldif
  • slapd -d 1 -f ./slapd.conf
    出现slapd starting则表示启动成功
  • slapadd -v -l ./mydemo.ldif
  • slapadd -v -l ./info.ldif
    出现100%…Closing…表示导入成功
  • 查看导入信息
    在ClientTools目录下打开cmd
    ldapsearch -x -b “dc=micmiu,dc=com” “(objectclass=*)”

删除数据

  • 先关闭服务,删除安装路径下data文件夹(默认路径)下的东西即可。
  • 具体目录在slapd.conf文件的directory标签后面的参数。

安装ldapbrowser

       安装的类型,建议选择第一个安装(Typical)

使用

  • New->New Profile并填写Profile:自定义
  • 填写Host,Port和Base DN
    Base DN可以按"Fetch Base DNs",然后自己选择
  • 填写Principal和Password

登陆信息

  • Host:localhost
  • Port:389
  • Base DN:dc=micmiu,dc=com
    上面这一项对应slapd.conf文件的suffix后面的参数
  • User DN(Principal):cn=Manager,dc=micmiu,dc=com
    上面这一项对应slapd.conf文件的rootdn后面的参数
  • Password:secret
    上面这一项对应slapd.conf文件的rootpw后面的参数
    默认值secret,默认基于{SSHA}加密
    {SSHA}n5e8W0KjKOkhPhpQ4gTdfeuaIG1E2NEI
  • 可以根据:
    C:\Users\Administrator>slappasswd
    New password: 123
    Re-enter new password: 123
    {SSHA}2e49d0L/XomzoVsO+VuWQbC5qixCdKK/

Java对Ldap的使用

package com.demo.database.other.ldap;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
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;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

public class LdapUtil {

	public static void main(String[] args) {
		// new LdapUtil().getOrgDN();
		// new LdapUtil().getUserDN();
	}

	// 声明静态变量只是例子,通常需要把这些参数写到配置文件中去
	private static String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
	// 链接的Host ldap://localhost/
	private static String URL = "ldap://localhost:389/";
	// 根据自己情况修改Base DN
	private static String BASEDN = "dc=micmiu,dc=com";

	// 管理员账号
	private static String PRINCIPAL = "cn=test,dc=micmiu,dc=com";
	// 管理员密码
	private static String PASSWORD = "123456789";
	private static String AUTHENTICATION = "simple";

	private LdapContext ctx = null;
	private final Control[] conControl = null;

	/**
	 * 进行LDAP连接
	 */
	private void openConnect() {
		Hashtable<String, String> hashTable = new Hashtable<String, String>();
		hashTable.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
		hashTable.put(Context.PROVIDER_URL, URL + BASEDN);
		hashTable.put(Context.SECURITY_AUTHENTICATION, AUTHENTICATION);
		hashTable.put(Context.SECURITY_PRINCIPAL, PRINCIPAL);
		hashTable.put(Context.SECURITY_CREDENTIALS, PASSWORD);

		try {
			ctx = new InitialLdapContext(hashTable, conControl);
			System.out.println("连接成功");
		} catch (javax.naming.AuthenticationException e) {
			System.out.println("连接失败");
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("连接失败");
			e.printStackTrace();
		}
	}

	/**
	 * 关闭LDAP连接
	 */
	private void closeConnect() {
		if (ctx != null) {
			try {
				ctx.close();
			} catch (NamingException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 遍历所有部门
	 * 
	 * @return
	 */
	public boolean getOrgDN() {
		boolean result = true;
		try {
			this.openConnect();
			String filter = "(&(|(objectClass=organizationalUnit)))";
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

			NamingEnumeration<SearchResult> en = ctx.search("", filter, constraints);

			while (en != null && en.hasMoreElements()) {
				Object obj = en.nextElement();
				if (obj instanceof SearchResult) {
					SearchResult sr = (SearchResult) obj;
					Attributes attrs = sr.getAttributes();

					// ou=Developer
					System.out.println(sr.getName());
					// 打印全部属性
					System.out.println("全部属性:\n" + attrs);
					// 打印单个属性
					System.out.println("单个属性:\n" + sr.getAttributes().get("description"));

					// 进行截取值
					if (sr.getAttributes().get("description") != null) {
						// description=description: xxx
						String des = sr.getAttributes().get("description").toString();
						System.out.println(des.substring(des.lastIndexOf(":") + 2, des.length()));
					}

					if (sr.getName() != null) {// 部门名称
						String orgname = sr.getName().toString();
						System.out.println(orgname.substring(orgname.lastIndexOf("=") + 1, orgname.length()));
					}

				} else {
					System.out.println(obj);
				}
			}
		} catch (Exception e) {
			result = false;
			e.printStackTrace();
		} finally {
			this.closeConnect();
		}
		return result;
	}

	/**
	 * 遍历所有用户
	 * 
	 * @return
	 */
	public boolean getUserDN() {
		boolean result = true;
		try {
			this.openConnect();
			String filter = "(&(|(objectClass=person)))";
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

			NamingEnumeration<SearchResult> en = ctx.search("", filter, constraints);

			while (en != null && en.hasMoreElements()) {
				Object obj = en.nextElement();
				if (obj instanceof SearchResult) {
					SearchResult sr = (SearchResult) obj;
					Attributes attrs = sr.getAttributes();

					// uid=565,ou=Developer
					System.out.println(sr.getName());
					// 全部属性
					System.out.println("全部属性:\n" + attrs);
					// 单个属性
					System.out.println("单个属性:\n" + sr.getAttributes().get("mail"));

					// 可在此处新建对象进行赋值
					if (sr.getAttributes().get("uid") != null) {// uid
						String uid = sr.getAttributes().get("uid").toString();
						System.out.println(uid.substring(uid.lastIndexOf(":") + 2, uid.length()));
					}

					if (sr.getAttributes().get("cn") != null) { // cn
						String cn = sr.getAttributes().get("cn").toString();
						System.out.println(cn.substring(cn.lastIndexOf(":") + 2, cn.length()));
					}
				} else {
					System.out.println(obj);
				}
			}
		} catch (Exception e) {
			result = false;
			e.printStackTrace();
		} finally {
			this.closeConnect();
		}
		return result;
	}

	/**
	 * 根据ldap中用户的mail字段与明文密码验证是否正确
	 * 
	 * @param mail
	 *            ldap中用户的mail字段
	 * @param password
	 *            输入的明文密码
	 * @return String 1:认证成功,0:认证失败,-1:此用户不存在
	 */
	public String authenticate(String mail, String password) {
		String result = "1";
		System.out.println("开始认证:" + mail);
		// 获取SSHA密文
		String sshapwd = getSSHAPwdByMail(mail);
		if ("".equals(sshapwd)) {
			result = "-1";
		}
		try {
			if (this.verifySSHA(sshapwd, password)) {
				result = "1";
				System.out.println(mail + ":认证通过");
			} else {
				result = "0";
				System.out.println(mail + ":认证失败");
			}
		} catch (IOException e) {
			result = "0";
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 根据ldap中用户的mail字段获取用户的LDAP{SSHA}密码
	 * 
	 * @param mail
	 *            ldap中用户的mail字段
	 * @return
	 */
	public String getSSHAPwdByMail(String mail) {
		String result = "";
		try {
			this.openConnect();
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			// 可以修改此处ldap中的属性
			NamingEnumeration<SearchResult> en = ctx.search("", "mail=" + mail, constraints);
			if (en == null || !en.hasMoreElements()) {
				result = "";
			}
			while (en != null && en.hasMoreElements()) {
				Object obj = en.nextElement();
				if (obj instanceof SearchResult) {
					SearchResult sr = (SearchResult) obj;
					Attributes attrs = sr.getAttributes();
					Attribute attr = attrs.get("userPassword");
					byte[] bytes = (byte[]) attr.get(0);
					result = new String(bytes);
				} else {
					System.out.println(obj);
				}
			}
		} catch (Exception e) {
			result = "";
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 根据ldap中用户的uid字段获取用户的userDN
	 * 
	 * @param uid
	 *            ldap中用户的uid字段
	 * @return
	 */
	public String getuserDNByUid(String uid) {
		String userDN = "";
		try {
			this.openConnect();
			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
			NamingEnumeration<SearchResult> en = ctx.search("", "uid=" + uid, constraints);
			if (en == null || !en.hasMoreElements()) {
				System.out.println("未找到该用户");
			}
			while (en != null && en.hasMoreElements()) {
				Object obj = en.nextElement();
				if (obj instanceof SearchResult) {
					SearchResult sr = (SearchResult) obj;
					userDN += sr.getName();
					userDN += "," + BASEDN;
				} else {
					System.out.println(obj);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return userDN;
	}

	/**
	 * 将明文与密文进行比较
	 * 
	 * @param ldappw
	 *            LDAP{SSHA}密文
	 * @param inputpw
	 *            明文
	 * @return
	 * @throws IOException
	 */
	public boolean verifySSHA(String ldappw, String inputpw) throws IOException {

		// MessageDigest提供了消息摘要算法,这里LDAP使用的是SHA-1
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		// 取出加密字符
		if (ldappw.startsWith("{SSHA}")) {
			ldappw = ldappw.substring(6);
		} else if (ldappw.startsWith("{SHA}")) {
			ldappw = ldappw.substring(5);
		}

		// 解码BASE64
		byte[] ldappwbyte = Base64.decode(ldappw);
		byte[] shacode;
		byte[] salt;

		// 前20位是SHA-1加密段,20位后是最初加密时的随机明文
		if (ldappwbyte.length <= 20) {
			shacode = ldappwbyte;
			salt = new byte[0];
		} else {
			shacode = new byte[20];
			salt = new byte[ldappwbyte.length - 20];
			System.arraycopy(ldappwbyte, 0, shacode, 0, 20);
			System.arraycopy(ldappwbyte, 20, salt, 0, salt.length);
		}
		// System.out.println(new String(shacode));

		// 把用户输入的密码添加到摘要计算信息
		md.update(inputpw.getBytes());
		// 把随机明文添加到摘要计算信息
		md.update(salt);

		// 按SSHA把当前用户密码进行计算
		byte[] inputpwbyte = md.digest();

		// 返回校验结果
		return MessageDigest.isEqual(shacode, inputpwbyte);
	}

}

问题

javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]

SECURITY_PRINCIPAL格式错误

javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]

①:slapd.conf文件不正确。sldap.conf文件中rootpw 配置,rootpw就写在行首,前面不能有空格,然后和密码之间使用tab键

②:修改slapd.conf文件rootpw后面的值(密码),然后重启slapd服务,发现密码并没有修改过来,还是只能用原来的密码登录,执行sudo slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d 时,密码才真正修改成功

③:确保用户名和密码正确

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值