由于业务需要,近期做了个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"))); attributeSet.add(new LDAPAttribute("userPrincipalName", "test"+"@test.com")); attributeSet.add(new LDAPAttribute("samAccountName", "tesst")); //attributeSet.add(new LDAPAttribute("datasource", "testSource")); //attributeSet.add(new LDAPAttribute("userpassword", new String("newpassword"))); LDAPEntry entry = new LDAPEntry("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的方式来解决此问题,或者是调用加密的链接。