Java程序通过LDAP对用户进行登陆验证

       在去年南京项目中,客户方要求用户登陆需要在其他平台下进行认证,当时客户用的LDAP“数据库”管理方式,后来查阅Java已经对LDAP进行了封装,不需要下载其他jar包就可以实现。

       补脑:【LDAP】是"Lightweight Directory Access Protocol"的缩写,中文翻译过来就叫“轻量目录访问协议”,看字面大概能猜出应该是以树状形存储数据的数据库,后来翻阅资料确实如此。其中包含几个重要的参数:CN,DN,DC,OU。至于这个缩写单词的含义,有兴趣可以去百科或者官网脑补一下,下面程序中将会引用这几个才参数,也会进行简单的描述。

package com.angma.mes.zbe.moudle.service.util;

import com.angma.mes.jagybarcode.manager.controller.plan.machine.MachineShopTaskCreateController;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

/**
 * 用户登陆认证,LDAP跨域认证,通过LDAP对用户进行更新
 *
 * @author xlj
 * @date 2015.07.10
 */
public class LdapUtil {

	private static DirContext ctx;

	// LDAP服务器端口默认为389
	private static final String LDAP_URL = "ldap://127.0.0.1:389";

	// ROOT根据此参数确认用户组织所在位置
	private static final String LDAP_PRINCIPAL = "OU=CMA Users,DC=changan-mazda,DC=com,DC=cn";

	// LDAP驱动
	private static final String LDAP_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";

	private static Logger logger = Logger.getLogger(LdapUtil.class);

	/**** 测试 ****/
	public static void main(String[] args) {
		LdapUtil.getLoginContext();
		LdapUtil.addUserLdap("10000", "123456");
		LdapUtil.updatePasswordLdap("10000", "1234567");
		LdapUtil.deleteUserLdap("10000");
	}

	// 通过连接LDAP服务器对用户进行认证,返回LDAP对象
	public static DirContext getLoginContext() {
		String account = "zhangsan"; // 模拟用户名
		String password = "123456"; // 模拟密码
		for (int i = 0; i < 5; i++) { // 验证次数
			Hashtable env = new Hashtable();
			env.put(Context.SECURITY_AUTHENTICATION, "simple");
			env.put(Context.SECURITY_CREDENTIALS, password);
			// cn=属于哪个组织结构名称,ou=某个组织结构名称下等级位置编号
			env.put(Context.SECURITY_PRINCIPAL, "cn=" + account + ", ou=Level0" + i + "00," + LDAP_URL);
			env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_PRINCIPAL);
			env.put(Context.PROVIDER_URL, LDAP_FACTORY);
			try {
				// 连接LDAP进行认证
				ctx = new InitialDirContext(env);
				System.out.println("认证成功");
				logger.info("【" + account + "】用户于【" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "】登陆系统成功");
			} catch (javax.naming.AuthenticationException e) {
				System.out.println("认证失败");
			} catch (NamingException err) {
				logger.info("--------->>【" + account + "】用户验证失败【" + i + "】次");
			} catch (Exception e) {
				System.out.println("认证出错:");
				e.printStackTrace();
			}
		}
		return ctx;
	}

	// 将输入用户和密码进行加密算法后验证
	public static boolean verifySHA(String ldappw, String inputpw) {

		// MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1
		MessageDigest md = MessageDigest.getInstance("SHA-1");

		// 取出加密字符
		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);
		}

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

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

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

	// 添加用户
	public static boolean addUserLdap(String account, String password) {
		boolean success = false;
		try {
			ctx = LdapUtil.getLoginContext();
			BasicAttributes attrsbu = new BasicAttributes();
			BasicAttribute objclassSet = new BasicAttribute("objectclass");
			objclassSet.add("person");
			objclassSet.add("top");
			objclassSet.add("organizationalPerson");
			objclassSet.add("inetOrgPerson");
			attrsbu.put(objclassSet);
			attrsbu.put("sn", account);
			attrsbu.put("uid", account);
			attrsbu.put("userPassword", password);
			ctx.createSubcontext("cn=" + account + ",ou=People", attrsbu);
			ctx.close();
			return true;
		} catch (NamingException ex) {
			try {
				if (ctx != null) {
					ctx.close();
				}
			} catch (NamingException namingException) {
				namingException.printStackTrace();
			}
			logger.info("--------->>添加用户失败");
		}
		return false;
	}

	// 修改密码
	public static boolean updatePasswordLdap(String account, String password) {
		boolean success = false;
		try {
			ctx = LdapUtil.getLoginContext();
			ModificationItem[] modificationItem = new ModificationItem[1];
			modificationItem[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", password));
			ctx.modifyAttributes("cn=" + account + ",ou=People", modificationItem);
			ctx.close();
			return true;
		} catch (NamingException ex) {
			try {
				if (ctx != null) {
					ctx.close();
				}
			} catch (NamingException namingException) {
				namingException.printStackTrace();
			}
			logger.info("--------->>修改密码失败");
		}
		return success;
	}

	// 删除用户
	public static boolean deleteUserLdap(String account) {
		try {
			ctx = LdapUtil.getLoginContext();
			ctx.destroySubcontext("cn=" + account);
		} catch (Exception ex) {
			try {
				if (ctx != null) {
					ctx.close();
				}
			} catch (NamingException namingException) {
				namingException.printStackTrace();
			}
			logger.info("--------->>删除用户失败");
			return false;
		}
		return true;
	}

	// 关闭LDAP服务器连接
	public static void closeCtx() {
		try {
			ctx.close();
		} catch (NamingException ex) {
			logger.info("--------->> 关闭LDAP连接失败");
		}
	}
}

声明:以上教程为博主原创,若需转载请注明出处,谢谢。

时间: 2024-10-10 09:47:54

Java程序通过LDAP对用户进行登陆验证的相关文章

java web程序 登陆验证页面 4个页面人性化设置

到这里,快期末考试了,老师不讲课,我心里有苦不想说,也许没有考虑到老师的感受,让老师难堪了 但是我的行为已不再是我可以做的了.不可能了,我只是职业性的机械的做事了. 思路: 1.第一个是form表单,用户输入用户名和密码,点击登陆按钮 a.jsp 2.第二是验证页面,如果不是那个用户名和密码,则显示登陆失败或错误,点击链接重新登陆ok.jsp d.jsp 3.当用户为输入任何数据,即为空的时候,则提示用户先登录,c.jsp 第一个页面,就不写了 验证页面 ok.jsp ? 1 2 3 4 5 6

[原创]java WEB学习笔记45:自定义HttpFilter类,理解多个Filter 代码的执行顺序,Filterdemo:禁用浏览器缓存的Filter,字符编码的Filter,检查用户是否登陆过的Filter

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

python操作mysql数据库小程序,用户登陆验证

已经建立一个mysql数据库school,里面包含一个表userinfo,表里有3个字段,分别为user_id,username,passwd,即序号(自增字段),用户名,密码. 已经该数据库中存放了若干用户的帐户信息,现在要求用python编写一段小程序,实现由用户输入自己的用户名和密码,完成登陆验证,输入正确的帐号, 显示"welcome",非正确的帐号,显示"failed log in" import pymysql conn = pymysql.connec

一个java程序员的真实经历

半路出家的老java程序员的一点感悟 我是一个老java程序员,现在基本告别编码时代了,当然我现在还在写代码,不是为了老板写了,是自己在创业.回想起这么多年的人生路,作为一名老程序员感慨颇多,尤其是作为一名半路出家的程序员,其中的滋味更是感慨万分.下面我就自己说说我的经历,也许会给未来码农一点启发. 首先讲讲我是怎么成为一个程序员的,这个还真要说说中国的教育.我们国家的这种应试教育一直受到很多人的诟病,有的指责扼杀了学生的创造力,有的指责培养出来的学生就像火腿厂生产的香肠,都是一个味毫无特点而言

分享下多年积累的对JAVA程序员成长之路的总结

http://blog.csdn.net/zhongzelin/article/details/8643269我也搞了几年JAVA了,由于一向懒惰,没有成为大牛,只是一普通程序猿,不爱玩社交网站,不爱玩微博,唯独喜欢百度贴吧,潜水很久了,手痒来给新人分享下从新手成长为老鸟的已见,也刷刷存在感,应该不比曝照差吧. 首先初识语法的阶段,必须要学会怎么操作对象,操作if和for,操作list set map,然后是线程.IO和jdbc什么的,其余的,若是一时不理解,可以后边需要时再学.这阶段完了,你可

Spring随笔06 利用LDAP校验用户

本小节将一步步教会你建立一个项目并给它添加Spring Security LDAP 模块. 你将建立一个 通过 Spring Security 提供的服务 来加密的程序, 该服务嵌入了 java 基本的 LDAP 加密. 你会通过加载一个配置了用户名密码集合的配置文件 来启动该服务. 1.建立一个简单的Controller.这个Controller向前端写回简单的一句话.如下: 1 package cn.tiny77.guide06; 2 3 import org.springframework

Oracle触发器反向调用Java程序

导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加载jlha.jar包,到oracle数据库中. 操作过程:在dos环境下,输入命令: loadjava -r -f -o -user usscares/[email protected] jlha.jar 注意:jar包要在1.4的环境下编译,项目右键 properties java compiler

一个java程序员自学IOS开发之路(四)

根据上图,由于我是一个Java程序员,前面两个阶段还是学的比较快的,但是由于电脑配置不行,光是开启虚拟机登陆OS系统就卡的不要不要的了,在那里面写代码简直是煎熬= =,后面的UI学习又要启动ios模拟器,根本无法进行. 于是下定决心,入手一台Macbook pro,告别我用了四年的联想~今天本本到货啦,哈哈^_^,可以愉快的继续了 2015/10/14 Day 15 为了便于开发者打造各式各样的优秀app,UIKit框架提供了非常多功能强大又易用的UI控件 2015/10/16 Day 16 第

java程序员培训:为什么要用Spring含三大框架简介

文章来源:http://www.zretc.com/technologyDetail/476.html Spring作为三大框架之一,一直困惑她有什么用?为什么要使用Spring呢?(大部分来自网上,引用出处太多,恕不一一标明.). SSH在J2EE项目中表示了3种框架,即 Spring + Struts +Hibernate. Struts对Model,View和Controller都提供了对应的组件.Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,它由Rod Jo