由于业务需要,近期做了个LDAP迁移WIN AD的方案,到网上查了很多资料,发现利用java无法往AD里写入用户密码以及自定义的字段。经过咨询microsoft的工程师,得到如下结论:

1、如果要往AD写用户密码,只能通过.net或者微软提供的接口。

2、要扩展AD的自定义属性,或者元素,通过注册Schmmgmt.dll,管理AD的架构。(注册方法:开始-->运行-->cmd-->确定-->regsvr32 Schmmgmt.dll.dll

 

具体操作方法如下:

 

一、首先定义自定义的属性(前提是已经注册好了Schmmgmt.dll.dll):

 

开始-->运行-->mmc-->确定
 
此时会弹出一个控制台,继续如下操作
 
文件-->添加管理单元-->Active Directory 架构-->添加-->确定
 
此时,展开MMC控制台最左边的的 Active Directory 架构树
右键点击属性-->新建-->属性-->继续 (以下是你自己需要的属性内容)
 
最后一步操作,展开类,将你新建的属性关联到类。

 

二、通过程序连接LDAP(我用的是JLDAP,当然,你可以用别的方式,网上资料很多,可以查查),伪代码如下:

 

import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPSearchResults;
import com.novell.ldap.LDAPEntry;
 
 
 
        String LDAP_Ip = "10.10.159.59";
        int LDAP_port = 389;
 LDAPConnection con = new LDAPConnection();
 con.connect(LDAP_Ip , LDAP_port);
 con.bind(LDAPConnection.LDAP_V3, "cn=directory manager","11111111");
 LDAPSearchResults rs = con.search("ou=People,dc=test,dc=com",
 LDAPConnection.SCOPE_SUB, "objectClass=*", null, false);
 
 
别忘了操作完了断开连接释放资源。

 

三、将查询到的数据写入AD(伪代码如下):

 

LDAPConnection con = new LDAPConnection();
con.connect("10.10.159.86", 389);
//连接AD时要注意,它的用户名为 登陆账户@域名
con.bind(LDAPConnection.LDAP_V3, "Administrator@test.com","pa$$word");
 
...获取LDAP的数据略
 
//以下是存储方法
 
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
 attributeSet.add(new LDAPAttribute("objectclass", new String("user")));
 attributeSet.add(new LDAPAttribute("objectclass", new String("top")));
 attributeSet.add(new LDAPAttribute("objectclass", new String("person")));
 attributeSet.add(new LDAPAttribute("objectclass", new String("organizationalPerson")));
"userPrincipalName", "test"+"@test.com"));
 attributeSet.add(new LDAPAttribute("samAccountName", "tesst"));
 //attributeSet.add(new LDAPAttribute("datasource", "testSource"));   
 //attributeSet.add(new LDAPAttribute("userpassword", new String("newpassword")));   
cn=test,CN=Users,DC=test,DC=com",attributeSet);
 con.add(entry);
con.disconnect();
//红色部分要注意,这是不同于LDAP的地方,LDAP是UID为唯一标识,但是,AD为CN。连接完以后记得释放资源。

 

三、.net修改密码(伪代码如下):

PS:我只学了半小时.net,以前完全没接触过,写得不好,别拍砖

 

modifyPass.aspx
 
<html>
 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>显示页面</title>
</head>
<body Style="padding:10px 0px 0px 0px">
<%@ import namespace="System.DirectoryServices" %>
<%@ import namespace="System.Web" %>
<%
String userName = Request.QueryString["userName"].ToString();
String passWord = Request.QueryString["passWord"].ToString();
string DomianPartA;
string DomianPartB;
string DomianName;
string DomainServerIP;
string DomianAdminName;
string DomianAdminPass;
DomianAdminName="administrator";
DomianAdminPass="Abcd1234,";
DomainServerIP="10.10.159.86";
DomianPartA="test" ;
DomianPartB="com";
DomianName= DomianPartA + "@" + DomianPartB;
//--添加用户
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry(DomainServer,DomianAdminName,DomianAdminPass, AuthenticationTypes.Secure);
System.DirectoryServices.DirectoryEntry subEntry = entry.Children.Find("CN=Users");
System.DirectoryServices.DirectoryEntry deUser = subEntry.Children.Find("cn="+userName);
deUser.Invoke("ChangePassword",new object[]{"",passWord});
deUser.Properties["userAccountControl"].Value = 0x200;
deUser.CommitChanges();
deUser.Close();
Response.Write("修改密码成功");
%> 
</body>
</html>

 

四、java远程调用,修改密码(伪代码如下):

 

String id = request.getParameter("id");
 
 String url = "http://"+ad_ip+"/modifyPass.aspx?userName="+ad+"&passWord=,Abcd1234";
 HttpClient client = new HttpClient();
 client.setConnectionTimeout(30 * 1000);
 HttpMethod method = new GetMethod(url);
 client.executeMethod(method);
 if (method.getStatusLine().toString().indexOf("200") > -1) {
 out.println("AD:"+method.getResponseBodyAsString()+"<br/>");
 out.flush();
 }
 method.releaseConnection();

 

五、测试是否通过:

 

login_ad.jsp
 
 
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ page
 import="java.util.Hashtable,javax.naming.Context,javax.naming.InvalidNameException,javax.naming.NamingEnumeration,javax.naming.NamingException,javax.naming.AuthenticationException,javax.naming.directory.Attribute,javax.naming.directory.Attributes,javax.naming.directory.BasicAttribute,javax.naming.directory.BasicAttributes,javax.naming.directory.DirContext,javax.naming.directory.SearchControls,javax.naming.directory.SearchResult,javax.naming.ldap.Control,javax.naming.ldap.InitialLdapContext,javax.naming.ldap.LdapContext,javax.naming.ldap.LdapName,javax.naming.Name"%>
<%@page import="com.novell.ldap.LDAPConnection"%>
<%@page import="com.novell.ldap.LDAPSearchResults"%>
<%@page import="com.novell.ldap.LDAPEntry"%>
<%@page import="com.novell.ldap.LDAPAttribute"%>
<%@page import="com.novell.ldap.LDAPAttributeSet"%>
<%
 String userName = request.getParameter("userName1");
 String userPass = request.getParameter("userPass1");
 LDAPConnection con = new LDAPConnection();
 con.connect("10.10.159.86", 389);
 //System.out.print(userName.split("\\,")[0].split("=")[1]);
 con.bind(LDAPConnection.LDAP_V3, userName+"@winda.com", userPass);
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试LDAP同步AD</title>
</head>
<body>
<%
 if(con != null){
 out.println("登陆成功!");
 }else{
 out.println("登陆失败!");
 }
%>
</body>
</html>

 

总结:

这只是给大家一个解决思路,此程序存在安全问题,修改密码的时候,从地址栏传参数是不允许的。可以通过.net搭建webservice的方式来解决此问题,或者是调用加密的链接。