JAVA使用Ldap操作AD域
项目上遇到的需要在集成 操作域用户的信息的功能,第一次接触ad域,因为不了解而且网上其他介绍不明确,比较费时,这里记录下。
说明:
(1). 特别注意:Java操作查询域用户信息获取到的数据和域管理员在电脑上操作查询的数据可能会存在差异(同一个意思的表示字段,两者可能不同)。
(2). 连接ad域有两个地址: ldap://XXXXX.com:389 和 ldap://XXXXX.com:636(SSL)。
(3). 端口389用于一般的连接,例如登录,查询等非密码操作,端口636安全性较高,用户密码相关操作,例如修改密码等。
(4). 域控可能有多台服务器,之间数据同步不及时,可能会导致已经修改的数据被覆盖掉,这个要么域控缩短同步的时间差,要么同时修改每一台服务器的数据。
1. 389登录
// 只要不抛出异常就是验证通过
public LdapContext adLogin(JSONObject json) {
String username = json.getString("username");
String password = json.getString("password");
String server = "ldap://XXXXXXX.com:389";
try {
Hashtable<String, String> env = new Hashtable<String, String>();
//用户名称,cn,ou,dc 分别:用户,组,域
env.put(Context.SECURITY_PRINCIPAL, username);
//用户密码 cn 的密码
env.put(Context.SECURITY_CREDENTIALS, password);
//url 格式:协议://ip:端口/组,域 ,直接连接到域或者组上面
env.put(Context.PROVIDER_URL, server);
//LDAP 工厂
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//验证的类型 "none", "simple", "strong"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
LdapContext ldapContext = new InitialLdapContext(env, null);
log.info("ldapContext:" + ldapContext);
log.info("用户" + username + "登录验证成功");
return ldapContext; } catch (NamingException e) {
log.info("用户" + username + "登录验证失败");
log.info("错误信息:"+e.getExplanation());
return null;
}
}
2. 636登录验证(需要导入证书)
//证书提前倒入的Java库中
// 参考:https://www.cnblogs.com/moonson/p/4454159.html LdapContext adLoginSSL(JSONObject json) {
String username = json.getString("username");
String password = json.getString("password");
Hashtable env = new Hashtable(); String javaHome = System.getProperty("java.home");
String keystore = javaHome+"/lib/security/cacerts";
log.info("java.home,{}",keystore);
// 加载导入jdk的域证书
System.setProperty("javax.net.ssl.trustStore", keystore);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
String LDAP_URL = "ldap://XXXXXX.com:636"; // LDAP访问地址 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_PROTOCOL, "ssl");//链接认证服务器
env.put(Context.PROVIDER_URL, LDAP_URL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
try {
LdapContext ldapContext = new InitialLdapContext(env, null);
log.info("认证成功");// 这里可以改成异常抛出。
return ldapContext;
} catch (javax.naming.AuthenticationException e) {
log.info("认证失败:{}",e.getMessage());
} catch (Exception e) {
log.info("认证出错:{}",e.getMessage());
}
return null;
}
3. 查询域用户信息
public List getUserKey(JSONObject json){
JSONObject admin = new JSONObject();
admin.put("username","Aaaaa");
admin.put("password", "bbbbbbbb");
String name = json.getString("name");
log.info("需要查询的ad信息:{}",name);
List<JSONObject> resultList = new JSONArray();
LdapContext ldapContext = adLogin(admin); //连接到域控
if (ldapContext!=null){
String company = "";
String result = "";
try {
// 域节点
String searchBase = "DC=XXXXXXX,DC=com";
// LDAP搜索过滤器类
//cn=*name*模糊查询
//cn=name 精确查询
// String searchFilter = "(objectClass="+type+")";
String searchFilter = "(sAMAccountName="+name+")"; //查询域帐号
// 创建搜索控制器
SearchControls searchCtls = new SearchControls();
String returnedAtts[]={"description","sAMAccountName","userAccountControl"};
searchCtls.setReturningAttributes(returnedAtts); //设置指定返回的字段,不设置则返回全部
// 设置搜索范围 深度
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter,searchCtls);
// 初始化搜索结果数为0
int totalResults = 0;
int rows = 0;
while (answer.hasMoreElements()) {// 遍历结果集
SearchResult sr = (SearchResult) answer.next();// 得到符合搜索条件的DN
++rows;
String dn = sr.getName();
log.info(dn);
Attributes Attrs = sr.getAttributes();// 得到符合条件的属性集
if (Attrs != null) {
try {
for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
Attribute Attr = (Attribute) ne.next();// 得到下一个属性
// 读取属性值
for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
company = e.next().toString();
JSONObject tempJson = new JSONObject();
tempJson.put(Attr.getID(), company.toString());
resultList.add(tempJson);
}
}
} catch (NamingException e) {
log.info("Throw Exception : " + e.getMessage());
}
}
}
log.info("总共用户数:" + rows);
} catch (NamingException e) {
log.info("Throw Exception : " + e.getMessage());
}finally {
try{
ldapContext.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
return resultList;
}
4. 重置用户密码
// 管理员重置用户密码,后强制用户首次登录修改密码
public Map<String, String> updateAdPwd(JSONObject json) {
String dn = json.getString("dn");//要修改的帐号(这个dn是查询的用户信息里的dn的值,而不是域账号)
String password = json.getString("password");//新密码 JSONObject admin = new JSONObject();
admin.put("username","aaaaaaa");
admin.put("password", "bbbbbbb");
Map<String,String> map = new HashMap<String,String>();
LdapContext ldapContext = adLoginSSL(admin); //连接636端口域
ModificationItem[] mods = new ModificationItem[2];
if (ldapContext!=null){
try {
String newQuotedPassword = "\"" + password + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
// unicodePwd:修改的字段,newUnicodePassword:修改的值
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("unicodePwd", newUnicodePassword));
mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("pwdLastSet", "0")); // 首次登录必须修改密码 // 修改密码
ldapContext.modifyAttributes(dn, mods);
map.put("result", "S");
map.put("message","成功");
}catch (Exception e){
map.put("result","E");
map.put("message", "无法重置密码");
}finally {
try{
ldapContext.close();
}catch (Exception e){
e.printStackTrace();
} } }else {
log.info("");
map.put("result","E");
map.put("message", "验证失败");
} return map;
}
5. 域账号解锁
// 表示锁定的字段需要测试,不一定这个lockoutTime
public Map<String, String> deblocking(JSONObject json) {
JSONObject admin = new JSONObject();
String dn = json.getString("dn"); //被解锁的帐号(这个dn指的是查询用户信息里的dn的值,不是域账号)
admin.put("username","aaaaaa");
admin.put("password","bbbbbb");
Map<String,String> map = new HashMap<String,String>();
LdapContext ldapContext = adLogin(admin);
ModificationItem[] mods = new ModificationItem[1];
if (ldapContext!=null){
try {
// "0" 表示未锁定,不为0表示锁定
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("lockoutTime","0"));
// 解锁域帐号
ldapContext.modifyAttributes(dn, mods);
map.put("result", "S");
map.put("message","成功");
}catch (Exception e){
map.put("result","E");
map.put("message", "解锁失败");
}finally {
try{
ldapContext.close();
}catch (Exception e){
e.printStackTrace();
} } }else {
map.put("result","E");
map.put("message", "验证失败");
}
return map;
}
JAVA使用Ldap操作AD域的更多相关文章
- Java使用LdAP获取AD域用户
随着我们的习大大上台后,国家在网络信息安全方面就有了非常明显的改变!所以如今好多做网络信息安全产品的公司和须要网络信息安全的公司都会提到用AD域server来验证,这里就简单的研究了一下! 先简单的讲 ...
- JAVA 通过LDAP获取AD域用户及组织信息
因为工作需求近期做过一个从客户AD域获取数据实现单点登录的功能,在此整理分享. 前提:用户可能有很多系统的情况下,为了方便账号的统一管理使用AD域验证登录,所以不需要我们的系统登录,就需要获取用户的A ...
- 利用LDAP操作AD域
LDAP操作代码样例 初始化LDAP 目录服务上下文 该例子中,我们使用uid=linly,ou=People,dc=jsoso,dc=net这个账号,链接位于本机8389端口的LDAP服务器(ld ...
- Java利用jcifs集成AD域用户认证
近期一段时间发现AD这东西老火了,尤其是涉及到安全这一方面的,所以AD域用户认证成了如今网络安全方面的产品必备!这里就简单的分享一下,Java通过jcifs集成AD域用户实现认证,以实现网络安全! 我 ...
- java集成微软的ad域,实现单点登录
1.ad域介绍: windos server 2008R2服务器下的ad域,见下图(我是在虚拟机安装到windos server) 2.连接ad域代码:(里面代码自行修改) public Result ...
- SonarQube 配置 LDAP(AD域)
安装插件 1.下载 LDAP Plugin 插件,地址:https://docs.sonarqube.org/display/SONARQUBE67/LDAP+Plugin2.将下载的插件,放到 SO ...
- AD 域服务简介(一)- 基于 LDAP 的 AD 域服务器搭建及其使用(转)
一.前言 1.1 AD 域服务 什么是目录(directory)呢? 日常生活中使用的电话薄内记录着亲朋好友的姓名.电话与地址等数据,它就是 telephone directory(电话目录):计算机 ...
- Ldap实现AD域认证
1.java Ldap基础类 package com.common; import java.io.FileInputStream; import java.io.IOException; impor ...
- 实验记录贴 —— 账号同步实验 RTX 和 LDAP(AD域)
目前,公司有多个系统,RTX,邮箱(MD),OA,NC. 这些系统之间,如果要实现单点登录的话,账户肯定需要同步,或者某一种映射机制. 如果所有数据都和中央账号数据库(LDAP,这里是AD域)看齐,那 ...
随机推荐
- mysql转oracle注意事项
1.mysql中有自增长,oracle用新建sequence代替. 2.在实体类的id要指定相关的sequence @GeneratedValue(strategy=GenerationType.SE ...
- Nginx+Tomcat+Memcached负载均衡和session共享
1. 演示搭建 说明:本文参考网络日志http://blog.csdn.net/remote_roamer/article/details/51133790,结合实际操作,仅做个演示记录. 1.1. ...
- 彻底来理解下hashmap吧
1.什么叫hashmap? 答:首先是一种map集合,其次呢,它是一种利用hash表来存储的数据结构.所以叫hashmap. 2.hashmap的特点是什么? 答:hashmap的特点是key值不能重 ...
- 大话设计模式C++实现-第8章-工厂方法模式
一.UML图 二.概念 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法是一个类的实例化延迟到其子类. 三.包括的角色 (1)抽象工厂 (2 ...
- 【结果发布】第六届SeedCoder编程大赛初赛结果发布
微软俱乐部科技文化月seedcoder2014编程大赛已经初审完成. 评审小组选出最棒的作品进入决赛(现场答辩+陈述环节,由评委现场打分).终于排名由"初赛分数+现场答辩分"决定. ...
- Lvs 负载均衡 (VS/NAT模式)
一.LVS简介 LVS是 Linux Virtual Server 的简称,也就是Linux虚拟服务器.这是一个由章文嵩博士发起的一个开源项目,它的官方网站是 http://www.linuxvirt ...
- Centos下mahout安装与配置
对于Mahout的安装与配置,须要一个前提.就是hadoop已经安装. 假设没有安装能够參考. http://blog.csdn.net/u012965373/article/details/4533 ...
- MySQL-数据更新(UPDATE)
MySQL-UPDATE语句 功能介绍:用于更新表中的现有数据.亦可用UPDATE语句来更改表中单个行,一组行或所有行的列值. MySQL-UPDATE语法: UPDATE [LOW_PRIORITY ...
- [办公自动化]如何在windows7中编辑hosts文件 (提示权限不够)
请按如下步骤尝试: 1.在开始菜单里,单击“所有程序”,找到“附件”,单击找到里面的“记事本”,右键,然后选择“以管理员身份运行”,如果有对话框,选择“是”.2.然后单击记事本窗口的“文件”菜单,选择 ...
- Apache2.2安装
貌似Apache官网从2.2.X之后不再发布Windows安装版本,需要的话得自己编译 从官网下载2.2.25(我下了一个no-ssl的),安装提示 因为本机已经安装IIS,占用80端口,修改Apac ...