熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

JNDI 連接Windows Active Directory&nb

2022-06-13   來源: Java核心技術 

  這編主要是描述 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 connection  or 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=


From:http://tw.wingwit.com/Article/program/Java/hx/201311/27091.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.