电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

JNDI 连接Windows Active Directory&nb


发布日期:2023/3/10
 

这编主要是描述 Java JNDI 连 Windows Active Directory 的教程

包括认证 新增用户 修改密码 及 取得用户资料

作者原文:

开始教程:

建立 IIS SSL

将 CA Certificate 加入至 jre keystore 里

JNDI 连 AD

建立 IIS SSL:

Install Windows Server:

Install AD:

Start > Run > dcpromote

domain name : joeytaDOTlocal

NT domain name : joeytaserver

即 Fully Qualified Domain Name (FQDN) 为 joeytaserverjoeytaDOTlocal

先安装 IIS 再安装 CA

Install IIS:

Start > Programs > Administrative Tools > Configure Your Server Wizard

>> Next > Next > Application server (IIS ASPNET) > Next

进入 表示安装成功

Install CA:

Start > Settings > Control Panel > Add or Remove Programs

>> Add/Remove Windows Components

选择 Certificate Services > Next

选择 Enterprise root CA > Next

Common name for this CA: testca > Next

进入 表示安装成功

Generating a Certificate Signing Request:

Start > Programs > Administrative Tools > Internet Information Services (IIS) Manager

>> Internet Information Services > (local computer) > Web Sites

> > 右键点选 Default Web Site > Properties

选择 Directory Security > Server Certificate

>> Create a new certificate > Prepare the request now but send it later

一直按 Next 需要注意的是 Common name 必须为 joeyserverjoeytalocal 这是给使用者连 ssl 的 website

最后产生 certificate request file 预设为 c:\certreqtxt

Request a certificate on CA:

进入

按 Request a certificate > advanced certificate request

> Submit a certificate request by using a baseencoded CMC or PKCS# file or submit a renewal request by using a baseencoded PKCS# file

使用 notepad 打开 c:\certreqtxt copy c:\certreqtxt 内容贴至 Saved Request:

Certificate Template 选择 Web Server 按 Submit

然后点选 Download certificate 将 certnewcer 储存至 c:\certnewcer

Installing a Certificate:

Start > Programs > Administrative Tools > Internet Information Services (IIS) Manager

>> Internet Information Services > (local computer) > Web Sites

> > 右键点选 Default Web Site > Properties

选择 Directory Security > Server Certificate

>> Process the pending request and install the certificate > Next

Path and file name: c:\certnewcer > Next

SSL port this web site should use: > Next > Next > Finish

将 CA Certificate 加入至 jre keystore 里:

进入

点选 Download a CA certificate certificate chain or CRL

点选 Download CA certificate 然后下载并改名为 c:\testca_certcer

然后执行 command:

c:\temp>keytool import alias testca_cert file /testca_certcer keystore /jdk_/jre/lib/security/cacerts storepass changeit

出现 Trusted this certificate? 按 y 即新增成功

JNDI 连 AD:

/***************************** LDAPFastBindjava *****************/

package testldap;

import javaioIOException;

import javaioUnsupportedEncodingException;

import javautilHashtable;

import javaxnamingAuthenticationException;

import javaxnamingContext;

import javaxnamingNamingEnumeration;

import javaxnamingNamingException;

import javaxnamingdirectoryAttribute;

import javaxnamingdirectoryAttributes;

import javaxnamingdirectoryBasicAttribute;

import javaxnamingdirectoryBasicAttributes;

import javaxnamingdirectoryDirContext;

import javaxnamingdirectoryModificationItem;

import javaxnamingdirectorySearchControls;

import javaxnamingdirectorySearchResult;

import javaxnamingldapControl;

import javaxnamingldapInitialLdapContext;

import javaxnamingldapLdapContext;

import javaxnamingldapStartTlsRequest;

import javaxnamingldapStartTlsResponse;

class FastBindConnectionControl implements Control {

public byte[] getEncodedValue() {

return null;

}

public String getID() {

return ;

}

public boolean isCritical() {

return true;

}

}

public class LDAPFastBind {

public Hashtable env = null;

public LdapContext ctx = null;

public Control[] connCtls = null;

public LDAPFastBind(String ldapurl) {

env = new Hashtable();

envput(ContextINITIAL_CONTEXT_FACTORY

comsunjndildapLdapCtxFactory);

envput(ContextSECURITY_AUTHENTICATION simple);

envput(ContextPROVIDER_URL ldapurl);

envput(ContextSECURITY_PROTOCOLssl);

String keystore = /jdk_/jre/lib/security/cacerts;

SystemsetProperty(ssltrustStorekeystore);

connCtls = new Control[] { new FastBindConnectionControl() };

// first time we initialize the context no credentials are supplied

// therefore it is an anonymous bind

try {

ctx = new InitialLdapContext(env connCtls);

} catch (NamingException e) {

Systemoutprintln(Naming exception + e);

}

}

public boolean Authenticate(String username String password) {

try {

ctxaddToEnvironment(ContextSECURITY_PRINCIPAL username);

ctxaddToEnvironment(ContextSECURITY_CREDENTIALS password);

ctxreconnect(connCtls);

Systemoutprintln(username + is authenticated);

return true;

}

catch (AuthenticationException e) {

Systemoutprintln(username + is not authenticated);

Systemoutprintln(e);

return false;

} catch (NamingException e) {

Systemoutprintln(username + is not authenticated);

Systemoutprintln(e);

return false;

}

}

public void finito() {

try {

ctxclose();

Systemoutprintln(Context is closed);

} catch (NamingException e) {

Systemoutprintln(Context close failure + e);

}

}

public void printUserAccountControl() {

try {

// Create the search controls

SearchControls searchCtls = new SearchControls();

// Specify the search scope

searchCtlssetSearchScope(SearchControlsSUBTREE_SCOPE);

// specify the LDAP search filter

//String searchFilter = (&(objectClass=user)(CN=test));

//String searchFilter = (&(objectClass=group));

String searchFilter = (&(objectClass=user)(CN=peter lee));

// Specify the Base for the search

String searchBase = DC=joeytaDC=local;

// initialize counter to total the group members

int totalResults = ;

// Specify the attributes to return

String returnedAtts[] = { givenName mail };

searchCtlssetReturningAttributes(returnedAtts);

// Search for objects using the filter

NamingEnumeration answer = ctxsearch(searchBase searchFilter

searchCtls);

// Loop through the search results

while (answerhasMoreElements()) {

SearchResult sr = (SearchResult) answernext();

Systemoutprintln(>>> + srgetName());

// Print out the groups

Attributes attrs = srgetAttributes();

if (attrs != null) {

try {

for (NamingEnumeration ae = attrsgetAll(); ae

hasMore();) {

Attribute attr = (Attribute) aenext();

Systemoutprintln(Attribute: + attrgetID());

for (NamingEnumeration e = attrgetAll(); e

hasMore(); totalResults++) {

Systemoutprintln( + totalResults +

+ enext());

}

}

} catch (NamingException e) {

Systemerrprintln(Problem listing membership: + e);

}

}

}

Systemoutprintln(Total attrs: + totalResults);

}

catch (NamingException e) {

Systemerrprintln(Problem searching directory: + e);

}

}

public boolean adminChangePassword(String sUserName String sNewPassword){

try {

//set password is a ldap modfy operation

ModificationItem[] mods = new ModificationItem[];

//Replace the unicdodePwd attribute with a new value

//Password must be both Unicode and a quoted string

String newQuotedPassword = \ + sNewPassword + \;

byte[] newUnicodePassword = newQuotedPasswordgetBytes(UTFLE);

mods[] = new ModificationItem(DirContextREPLACE_ATTRIBUTE

new BasicAttribute(unicodePwd newUnicodePassword));

// Perform the update

ctxmodifyAttributes(sUserName mods);

Systemoutprintln(Reset Password for: + sUserName);

return true;

}

catch (NamingException e) {

Systemoutprintln(Problem resetting password: + e);

}

catch (UnsupportedEncodingException e) {

Systemoutprintln(Problem encoding password: + e);

}

return false;

}

public boolean userChangePassword(String sUserName String sOldPassword

String sNewPassword){

try {

//StartTlsResponse tls=

//(StartTlsResponse)ctxextendedOperation(new StartTlsRequest());

//tlsnegotiate();

//change password is a single ldap modify operation

//that deletes the old password and adds the new password

ModificationItem[] mods = new ModificationItem[];

//Firstly delete the unicdodePwd attribute using the old password

//Then add the new passwordPasswords must be both Unicode and a quoted string

String oldQuotedPassword = \ + sOldPassword + \;

byte[] oldUnicodePassword = oldQuotedPasswordgetBytes(UTFLE);

String newQuotedPassword = \ + sNewPassword + \;

byte[] newUnicodePassword = newQuotedPasswordgetBytes(UTFLE);

mods[] = new ModificationItem(DirContextREMOVE_ATTRIBUTE

new BasicAttribute(unicodePwd oldUnicodePassword));

mods[] = new ModificationItem(DirContextADD_ATTRIBUTE

new BasicAttribute(unicodePwd newUnicodePassword));

// Perform the update

ctxmodifyAttributes(sUserName mods);

Systemoutprintln(Changed Password for: + sUserName);

//tlsclose();

return true;

}

catch (NamingException e) {

Systemerrprintln(Problem changing password: + e);

}

catch (UnsupportedEncodingException e) {

Systemerrprintln(Problem encoding password: + e);

} catch ( Exception e){

Systemerrprintln(Problem: + e);

}

return false;

}

public boolean createNewUser(String sGroupName String sUserName){

try {

// Create attributes to be associated with the new user

Attributes attrs = new BasicAttributes(true);

//These are the mandatory attributes for a user object

//Note that WinK will automagically create a random

//samAccountName if it is not present (WinK does not)

attrsput(objectClassuser);

attrsput(sAMAccountNameAlanT);

attrsput(cnAlan Tang);

//These are some optional (but useful) attributes

attrsput(givenNameAlan);

attrsput(snTang);

attrsput(displayNameAlan Tang);

attrsput(descriptionEngineer);

attrsput(userPrincipalNamealanATjoeytalocal);

attrsput(mailalangATmailjoeytaDOTlocal);

attrsput(telephoneNumber );

//some useful constants from lmaccessh

int UF_ACCOUNTDISABLE = x;

int UF_PASSWD_NOTREQD = x;

int UF_PASSWD_CANT_CHANGE = x;

int UF_NORMAL_ACCOUNT = x;

int UF_DONT_EXPIRE_PASSWD = x;

int UF_PASSWORD_EXPIRED = x;

//Note that you need to create the user object before you can

//set the password Therefore as the user is created with no

//password user AccountControl must be set to the following

//otherwise the WinK password filter will return error

//unwilling to perform

attrsput(userAccountControlIntegertoString

(UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD + UF_PASSWORD_EXPIRED+ UF_ACCOUNTDISABLE));

// Create the context

Context result = ctxcreateSubcontext(sUserName attrs);

Systemoutprintln(Created disabled account for: + sUserName);

//now that weve created the user object we can set the

//password and change the userAccountControl

//and because password can only be set using SSL/TLS

//lets use StartTLS

//StartTlsResponse tls = (StartTlsResponse)ctxextendedOperation

(new StartTlsRequest());

//tlsnegotiate();

//set password is a ldap modfy operation

//and well update the userAccountControl

//enabling the acount and force the user to update ther password

//the first time they login

ModificationItem[] mods = new ModificationItem[];

//Replace the unicdodePwd attribute with a new value

//Password must be both Unicode and a quoted string

String newQuotedPassword = \PATsswrd\;

byte[] newUnicodePassword = newQuotedPasswordgetBytes(UTFLE);

mods[] = new ModificationItem(DirContextREPLACE_ATTRIBUTE

new BasicAttribute(unicodePwd newUnicodePassword));

mods[] = new ModificationItem(DirContextREPLACE_ATTRIBUTE

new BasicAttribute(userAccountControl

IntegertoString(UF_NORMAL_ACCOUNT + UF_PASSWORD_EXPIRED)));

// Perform the update

ctxmodifyAttributes(sUserName mods);

Systemoutprintln(Set password & updated userccountControl);

//now add the user to a group

try{

ModificationItem member[] = new ModificationItem[];

member[]= new ModificationItem(DirContextADD_ATTRIBUTE

new BasicAttribute(member sUserName));

ctxmodifyAttributes(sGroupNamemember);

Systemoutprintln(Added user to group: + sGroupName);

}

catch (NamingException e) {

Systemerrprintln(Problem adding user to group: + e);

}

//Could have put tlsclose()prior to the group modification

//but it seems to screw up the connectionor context ?

//tlsclose();

Systemoutprintln(Successfully created User: + sUserName);

return true;

}

catch (NamingException e) {

Systemerrprintln(Problem creating object: + e);

}

catch (IOException e) {

Systemerrprintln(Problem creating object: + e);

}

return false;

}

public boolean addUserToGroup(LdapContext ctx String userDN String groupDN)

{

try{

ModificationItem[] mods = new ModificationItem[];

mods[] = new ModificationItem(DirContextADD_ATTRIBUTE

new BasicAttribute(member userDN));

ctxmodifyAttributes(groupDN mods);

Systemoutprintln(Added user + userDN + to group + groupDN);

return true;

} catch (NamingException ne){

Systemerrprintln(Problem add user to group: + ne);

}

return false;

}

public boolean removeUserFromGroup(LdapContext ctx String userDN

String groupDN) {

try{

ModificationItem[] mods = new ModificationItem[];

mods[] = new ModificationItem(DirContextREMOVE_ATTRIBUTE

new BasicAttribute(member userDN));

ctxmodifyAttributes(groupDN mods);

Systemoutprintln(Remove user + userDN + from group + groupDN);

return true;

} catch (NamingException ne){

Systemerrprintln(Problem remove user from group: + ne);

}

return false;

}

}

/***************************** LDAPFastBindjava *****************/

/***************************** LDAPClientjava *****************/

package testldap;

class LDAPClient {

public static void main(String[] args) {

// Could also use ldaps over port to protect the communication to

// the

// Active Directory domain controller Would also need to add

// envput(ContextSECURITY_PROTOCOLssl) to the server code

//String ldapurl = ldap://joeyserverjoeytalocal:;

String ldapurl = ldap://joeyserverjoeytalocal:;

LDAPFastBind ctx = new LDAPFastBind(ldapurl);

String sAdminUserName = CN=AdministratorCN=UsersDC=joeytaDC=local;

String sAdminPassword = I@mRoot;

//String sUserName = CN=peter leeCN=UsersDC=joeytaDC=local;

String sUserName = joeyta\\peter;

//String sUserName = peter@joeytalocal;

String sOldPassword = P@sswrd;

String sNewPassword = P@$$wrd;

String sNewUserName = CN=Alan TangCN=UsersDC=joyetaDC=local;

String sNewGroupName = CN=testCN=UsersDC=joeytaDC=local;

boolean IsAuthenticated = ctxAuthenticate(sAdminUserName sAdminPassword);

//boolean IsAuthenticated = ctxAuthenticate(sUserName sOldPassword);

ctxprintUserAccountControl();

ctxcreateNewUser(sNewGroupName sNewUserName);

//boolean IsAdminSuccessChangePWD =

//ctxadminChangePassword(sUserNamesNewPassword);

//boolean IsUserSuccessChangePWD =

//ctxuserChangePassword(sUserNamesOldPasswordsNewPassword);

ctxfinito();

}

}

/***************************** LDAPClientjava *****************/

参考资料:

;id=&sty=&tpg=&age=

a?forumID=&start=

上一篇:使用PreparedStatement减少开发时间

下一篇:冒泡排序与插入排序