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域)看齐,那 ...
随机推荐
- 记一次springMVC的跨域解决方案
日期:2019年5月18日 事情原因:由于微信小程序的开发只有测试环境,而后台提供借口的环境是开发环境:两个环境的域名不同,导致前端开发产生了跨域问题: 理论概念: 1.同源策略:同源策略是浏览器的安 ...
- SQL PATINDEX检索
语法格式:PATINDEX ( '%pattern%' , expression ) 返回pattern字符串在表达式expression里第一次出现的位置,起始值从1开始算. pattern字符串在 ...
- AE After Effect 如何分段渲染
如果只要第一段的话,你把要输出的那段首尾处分别按下B键和N键,这样输出时就会只输出这一段了(拖动首尾的栏目修改起始和终止的时间):如果是批量渲染的话你只要在这些不同的合成层里,每个按下ctrl+M键, ...
- yarn-cli 缓存
yarn cache list Yarn 会在你的用户目录下开辟一块全局缓存用以保存下载的包.yarn cache list 用于列出所有已经缓存的包. yarn cache dir 执行 yarn ...
- HDU 1796 How many integers can you find(容斥原理+二进制/DFS)
How many integers can you find Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 ...
- javaweb_page指令
jsp指令: 1.作用:jsp指令是为jsp引擎设计的.他们并不直接产生不论什么课件输出.而是告诉引擎怎样处理jsp页面中的其余部分 2.jsp指令包含:page指令.include指令,taglib ...
- 经典面试题回答——学习Java基础的目的
本系列知识解释:相信每个学习Java的人都是从JavaSE開始的,也就是Java基础開始. 可是却并不清楚学习Java基础究竟有什么用? 首先我来回答这个问题,学习Java基础是有两个目 ...
- 64位win2008下IIS未开启32位支持导致DLL无法加载问题
部署一个WEB项目,在本机.本地服务器都没有问题,但部署到远程服务器以后,提示有个DLL无法加载: Server Error in '/' Application. Could not load fi ...
- mciSendString详解(转)
做个mp3播放器,用realplay和WMP做出来的程序内存占用太大.如果你仅仅是播放MP3,建议使用API函数mciSendString,我把该函数的详细资料罗列如下供你参考.Option Expl ...
- 获取特定html源码 富文本编辑器 爬虫生成 dom
python beautifulsoup获取特定html源码 - 吴悟无 - 博客园 https://www.cnblogs.com/vickey-wu/p/6843411.html PyQuery库 ...