Kimi's NutShell

          我荒廢的今日,正是昨日殞身之人祈求的明日

          BlogJava 新隨筆 管理
            141 Posts :: 0 Stories :: 75 Comments :: 0 Trackbacks

          這是個人1周來學習LDAP和web service的總結,如果覺的不好,請評價;如有轉載,請注明出處~

          屬性BEAN:

          package com.primesuccess.ldap;

          import java.io.IOException;

          import java.util.Enumeration;
          import java.util.Properties;
          import java.util.ResourceBundle;


          /**
          ?* Contains static variables which define the connection parameters
          ?* for Oracle Internet Directory and Database. The parameters are loaded from
          ?* Connection.properties file.
          ?*
          ?*/
          public class ConnParams {
          ??? // Default Root Context
          ??? public static String identityMgmtRealm = null;

          ??? // DataSource name
          ??? public static String groceryDSName = null;

          ??? // Directory Server host name
          ??? public static String dirHostName = null;

          ??? // Directory instance? port
          ??? public static String dirPort = null;
          ??? public static String adminname = null;
          ??? public static String adminpassword = null;
          ??? public static String objC1 = null;
          ??? public static String objC2 = null;
          ??? public static String objC3 = null;
          ??? public static String objC4 = null;
          ??? public static String objC5 = null;
          ??? public static String objC6 = null;
          ??? public static String RDN=null;
          ??? public static String userctx=null;

          ??? // Load parameters from Connection.properties
          ??? static {
          ??????? if (identityMgmtRealm == null) {
          ??????????? Properties conValues = null;

          ??????????? try {
          ??????????????? // Parse the Connection.properties file and extract the details
          ??????????????? conValues = loadParams("Connection");

          ??????????????? // Get the details from the Properties
          ??????????????? groceryDSName = (String) conValues.getProperty(
          ??????????????????????? "DATASOURCE_NAME");
          ??????????????? dirHostName = (String) conValues.getProperty("LDAP_HOST_NAME");
          ??????????????? dirPort = (String) conValues.getProperty("LDAP_PORT");
          ??????????????? identityMgmtRealm = (String) conValues.getProperty(
          ??????????????????????? "IDENTITY_MGMT_REALM");
          ??????????????? adminname = (String) conValues.getProperty("LDAP_ADMIN_NAME");
          ??????????????? adminpassword = (String) conValues.getProperty(
          ??????????????????????? "LDAP_ADMIN_PASSWORD");
          ??????????????? objC1 = (String) conValues.getProperty("ldap_obj1");
          ??????????????? objC2 = (String) conValues.getProperty("ldap_obj2");
          ??????????????? objC3 = (String) conValues.getProperty("ldap_obj3");
          ??????????????? objC4 = (String) conValues.getProperty("ldap_obj4");
          ??????????????? objC5 = (String) conValues.getProperty("ldap_obj5");
          ??????????????? objC6 = (String) conValues.getProperty("ldap_obj6");
          ??????????????? RDN=(String)conValues.getProperty("ldap_RDN");
          ??????????????? userctx=(String)conValues.getProperty("ldap_userctx");
          ???????????????
          ??????????? } catch (Exception ex) {
          ??????????????? System.out.println(
          ??????????????????? " Fatal Error : Could not read Properties file : " +
          ??????????????????? ex.toString());
          ??????????? } finally {
          ??????????????? // Clear properties
          ??????????????? conValues.clear();
          ??????????????? conValues = null;
          ??????????? }
          ??????? }
          ??? }

          ??? /**
          ???? * This method reads a properties file which is passed as
          ???? * the parameter to it and returns it as Properties object.
          ???? *
          ???? * @param file File path
          ???? * @return Properties The properties object
          ???? * @exception IOException if loading properties file fails
          ???? */
          ??? public static Properties loadParams(String file) throws IOException {
          ??????? // Loads a ResourceBundle and creates Properties from it
          ??????? Properties prop = new Properties();
          ??????? ResourceBundle bundle = ResourceBundle.getBundle(file);

          ??????? // Retrieve the keys and populate the properties object
          ??????? Enumeration enum = bundle.getKeys();
          ??????? String key = null;

          ??????? while (enum.hasMoreElements()) {
          ??????????? key = (String) enum.nextElement();

          ??????????? prop.put(key, bundle.getObject(key));
          ??????? }

          ??????? return prop;
          ??? }
          }


          接口BEAN:

          package com.primesuccess.ldap;

          import java.util.ArrayList;
          import java.util.Collection;
          import java.util.Hashtable;
          import java.util.Iterator;
          import java.util.List;
          import java.util.Map;

          import javax.naming.AuthenticationException;
          import javax.naming.Context;
          import javax.naming.NameAlreadyBoundException;
          import javax.naming.NamingEnumeration;
          import javax.naming.NamingException;
          import javax.naming.directory.Attribute;
          import javax.naming.directory.Attributes;
          import javax.naming.directory.BasicAttribute;
          import javax.naming.directory.BasicAttributes;
          import javax.naming.directory.DirContext;
          import javax.naming.directory.InitialDirContext;
          import javax.naming.directory.SearchControls;
          import javax.naming.directory.SearchResult;


          /**
          ?* This class manages all Directory operations.
          ?*/
          public class DirectoryManager {
          ??? public DirContext dirctx = null;
          ???

          ??? /**
          ???? * Empty default Constructor.
          ???? */
          ??? public DirectoryManager() {
          ??? }

          ??? /**
          ???? *? Authenticates the user credentials with Directory.
          ???? *
          ???? *? @param username? User Name of the user
          ???? *? @param passwd Password of the user
          ???? *? @return? true - if the credentials are valid
          ???? *
          ???? *? @exception AuthenticationException If credentials are invalid
          ???? *? @exception NamingException if any directory operation fails
          ???? *? @webmethod
          ???? */
          ??? public boolean authenticateUser(String username, String passwd)
          ??????? throws AuthenticationException, NamingException {
          ??????? boolean authorized = false;

          ??????? // Get the Distinguished Name
          ??????? String dn = this.getUserDN(username);

          ??????? try {
          ??????????? // Authenticate with Directory
          ??????????? dirctx = this.getDirectoryContext(dn, passwd);
          ??????????? authorized = true;
          ??????? } catch (AuthenticationException authEx) {
          ??????????? throw new AuthenticationException(" Invalid Password ");
          ??????? }

          ??????? return authorized;
          ??? }

          ??? public int changeEmail(String username, String newemail)
          ??????? throws Exception {
          ??????? try {
          ??????????? Attributes attrs = new BasicAttributes(true);

          ??????????? if (com.primesuccess.ldap.ValidatorEx.doValidateEmail(newemail) == 1) {
          ??????????????? attrs.put(new BasicAttribute("mail", newemail));
          ??????????????? dirctx.modifyAttributes(getUserDN(username),
          ??????????????????? DirContext.REPLACE_ATTRIBUTE, attrs);

          ??????????????? return 1;
          ??????????? } else {
          ??????????????? return ValidatorEx.doValidateEmail(newemail);
          ??????????? }
          ??????? } catch (Exception e) {
          ??????????? e.printStackTrace();

          ??????????? return -2;
          ??????? }
          ??? }

          ??? public int changePassword(String username, String oldpassword,
          ??????? String newpassword) throws Exception {
          ??????? try {
          ??????????? Attributes attrs = new BasicAttributes(true);

          ??????????? if (authenticateUser(username, oldpassword)) {
          ??????????????? if (com.primesuccess.ldap.ValidatorEx.doValidatePassword(
          ??????????????????????????? newpassword) == 1) {
          ??????????????????? attrs.put(new BasicAttribute("userpassword", newpassword));
          ??????????????????? dirctx.modifyAttributes(getUserDN(username),
          ??????????????????????? DirContext.REPLACE_ATTRIBUTE, attrs);

          ??????????????????? return 1;
          ??????????????? } else {
          ??????????????????? return ValidatorEx.doValidatePassword(newpassword);
          ??????????????? }
          ??????????? } else {
          ??????????????? return -1;
          ??????????? }
          ??????? } catch (Exception e) {
          ??????????? e.printStackTrace();

          ??????????? return -2;
          ??????? }
          ??? }

          ??? public int validUser(String name, String tag) throws Exception {
          ??????? try {
          ??????????? Attributes attrs = new BasicAttributes(true);
          ??????????? String dn = getUserDN(name);
          ??????????? if (tag.equals("ENABLED")||tag.equals("disabled")) {
          ??????????????? attrs.put(new BasicAttribute("orclisenabled", tag));
          ??????????????? dirctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs);
          ??????????????? return 1;
          ??????????? }
          ?????????? else
          ?????????? {
          ???????????? return -1;
          ?????????? }
          ??????? } catch (Exception e) {
          ??????????? return -2;
          ??????? }
          ??? }

          ??? public void addDirectoryEntry(String dn, List objCls, Map map)
          ??????? throws NamingException, NameAlreadyBoundException {
          ??????? // Create attribute list, ignore case of attribute names
          ??????? Attributes attrs = new BasicAttributes(true);

          ??????? if (!objCls.isEmpty()) {
          ??????????? Attribute objclass = new BasicAttribute("objectclass");

          ??????????? // Iterate thriough the collection and add the object classes to the attribute
          ??????????? Iterator objclsIter = objCls.iterator();

          ??????????? while (objclsIter.hasNext()) {
          ??????????????? // Add the object classes???????
          ??????????????? objclass.add(objclsIter.next());
          ??????????? }

          ??????????? // Add the object class attribute to list
          ??????????? attrs.put(objclass);
          ??????? }

          ??????? // Iterate through other attributes and add to attributes list
          ??????? Iterator attrsIter = map.entrySet().iterator();

          ??????? while (attrsIter.hasNext()) {
          ??????????? Map.Entry attr = (Map.Entry) attrsIter.next();
          ??????????? attrs.put(new BasicAttribute((String) attr.getKey(), attr.getValue()));
          ??????? }

          ??????? // add the directory entry to the directory with the attributes
          ??????? dirctx.createSubcontext(dn, attrs);
          ??? }

          ??? /**
          ???? * Retrieves the Distinguished name of them of the specified RDN.
          ???? *
          ???? * @param uname? Relative Distinguished name.
          ???? * @return? Distinguished name of the user
          ???? * @exception NamingException if directory operation fails
          ???? */
          ??? public String getUserDN(String uname) throws NamingException {
          ??????? DirContext dCtx = null;

          ??????? // if Grocery context is available, use it, else create one as application entity
          ??????? if (dirctx == null) {
          ??????????? dCtx = this.getDirectoryContext(ContextNames.userContext, "");
          ??????? } else {
          ??????????? dCtx = dirctx;
          ??????? }

          ??????? SearchResult searchResult = null;
          ??????? NamingEnumeration results = null;
          ??????? String userDN = null;
          ??????? String filter = "(" + ContextNames.RDN + "=" + uname + ")";

          ??????? // To set search controls to search with subtree scope
          ??????? SearchControls searchControls = new SearchControls();
          ??????? searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

          ??????? // Search the directory based on the search string from the specified context
          ??????? results = dCtx.search(ContextNames.userContext, filter, searchControls);

          ??????? // If matching record found
          ??????? if (results.hasMore()) {
          ??????????? searchResult = (SearchResult) results.next();

          ??????????? // Build the User DN
          ??????????? userDN = searchResult.getName() + "," + ContextNames.userContext;
          ??????? } else {
          ??????????? // User not found
          ??????????? throw new NamingException(" Invalid Username ");
          ??????? }

          ??????? return userDN;
          ??? }

          ??? /**
          ???? *? Initializes a Directory Context with the specified credentials and return it.
          ???? *? If the password is blank(null), it binds as anonymous user and returns the
          ???? *? context.
          ???? *
          ???? * @param username Directory user name
          ???? * @param password Directory user password
          ???? * @return? valid directory context, if credentials are valid
          ???? * @exception AuthenticationException? if credentails are invalid
          ???? * @exception NamingException if directory operation fails
          ???? */
          ??? public DirContext getDirectoryContext(String username, String password)
          ??????? throws AuthenticationException, NamingException {
          ??????? //DirContext dCtx = null;
          ??????? //Build the LDAP url
          ??????? String ldapurl = "ldap://" + ConnParams.dirHostName + ":" +
          ??????????? ConnParams.dirPort;

          ??????? Hashtable env = new Hashtable();
          ??????? env.put(Context.INITIAL_CONTEXT_FACTORY,
          ??????????? "com.sun.jndi.ldap.LdapCtxFactory");
          ??????? env.put(Context.PROVIDER_URL, ldapurl);

          ??????? // if password is specified, set the credentials
          ??????? if (password != null) {
          ??????????? env.put(Context.SECURITY_AUTHENTICATION, "simple");
          ??????????? env.put(Context.SECURITY_PRINCIPAL, username);
          ??????????? env.put(Context.SECURITY_CREDENTIALS, password);
          ??????? }

          ??????? // Bind and initialize the Directory context
          ??????? dirctx = new InitialDirContext(env);

          ??????? return dirctx;
          ??? }

          ??? /**
          ???? * Searchs the directory under the specified context with specified filter
          ???? * and returns the search results.
          ???? * The scope is set to one-level.
          ???? *
          ???? * @param ctxname Context under which seach has to be done.
          ???? * @param filter Search filter
          ???? * @return? Attributes matching the search specification
          ???? * @exception NamingException if directory search fails
          ???? */
          //????? public boolean searchAssembly(String name) throws Exception {
          //??????
          //??????????? list = search(name).iterator();
          //
          //??????????? return true;
          //??????? } else {
          //??????? return false;
          //??????? }
          //??? }
          ??? public Collection search(String ctxname, String filter)
          ??????? throws NamingException {
          ??????? SearchResult searchResult = null;
          ??????? NamingEnumeration results = null;
          ??????? Collection retColl = new ArrayList();
          ??????? Attributes attrs = null;

          ??????? // Initialize search search controls with one-level scope
          ??????? SearchControls searchControls = new SearchControls();
          ??????? searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);

          ??????? // Search the directory based on the search string under the specified context
          ??????? results = dirctx.search(ctxname, filter, searchControls);

          ??????? // Check if any matching results were found in Directory
          ??????? if (results.hasMore()) {
          ??????????? // Iterate through the results and populate the return collection
          ??????????? do {
          ??????????????? searchResult = (SearchResult) results.next();

          ??????????????? // Get the attributes
          ??????????????? attrs = searchResult.getAttributes();

          ??????????????? retColl.add(attrs);
          ??????????? } while (results.hasMore());
          ??????? }

          ??????? return retColl;
          ??? }
          }

          用戶操作BEAN(WEB SERVICE上可見):
          package com.primesuccess.ldap;

          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.Iterator;
          import java.util.Vector;

          import javax.naming.AuthenticationException;
          import javax.naming.NamingException;
          import javax.naming.directory.Attribute;
          import javax.naming.directory.Attributes;
          import javax.naming.directory.BasicAttribute;
          import javax.naming.directory.BasicAttributes;
          import javax.naming.directory.DirContext;


          public class LdapBean {
          ??? private boolean isLogin = false;
          ??? Iterator list;

          ??? public LdapBean() {
          ??? }

          ??? /**
          ??? *? Authenticates the user credentials with Directory.
          ??? *
          ??? *? @param username? User Name of the user
          ??? *? @param passwd Password of the user
          ??? *? @return? true - if the credentials are valid
          ??? *
          ??? *? @exception AuthenticationException If credentials are invalid
          ??? *? @exception NamingException if any directory operation fails
          ??? *? @webmethod
          ??? */
          ??? public boolean authenticateUser(String username, String passwd)
          ??????? throws AuthenticationException, NamingException {
          ??????? DirectoryManager dm = new DirectoryManager();

          ??????? return dm.authenticateUser(username, passwd);
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public int changeEmail(String username, String newemail)
          ??????? throws Exception {
          ??????? if (isLogin()) {
          ??????????? DirectoryManager dm = new DirectoryManager();
          ??????????? String dn = dm.getUserDN(ConnParams.adminname);
          ??????????? dm.dirctx = dm.getDirectoryContext(dn, ConnParams.adminpassword);

          ??????????? return dm.changeEmail(username, newemail);
          ??????? } else {
          ??????????? return 0;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public int createUser(String name, String password, String email) {
          ??????? if (isLogin()) {
          ??????????? try {
          ??????????????? DirectoryManager dm = new DirectoryManager();
          ??????????????? String dn = dm.getUserDN(ConnParams.adminname);
          ??????????????? dm.dirctx = dm.getDirectoryContext(dn, ConnParams.adminpassword);

          ??????????????? ArrayList objList = new ArrayList();
          ??????????????? HashMap map = new HashMap();
          ??????????????? objList.add(0, ConnParams.objC1);
          ??????????????? objList.add(1, ConnParams.objC2);
          ??????????????? objList.add(2, ConnParams.objC3);
          ??????????????? objList.add(3, ConnParams.objC4);
          ??????????????? objList.add(4, ConnParams.objC5);
          ??????????????? objList.add(5, ConnParams.objC6);
          ??????????????? map.put("cn", name);
          ??????????????? map.put("sn", name);
          ??????????????? map.put("uid", name);
          ??????????????? map.put("mail", email);
          ??????????????? map.put("userpassword", password);
          ??????????????? dm.addDirectoryEntry(ConnParams.RDN + "=" + name + "," +
          ??????????????????? ConnParams.userctx, objList, map);

          ??????????????? return 1;
          ??????????? } catch (Exception e) {
          ??????????????? e.printStackTrace();

          ??????????????? return -1;
          ??????????? }
          ??????? } else {
          ??????????? return 0;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public int changePassword(String username, String oldpassword,
          ??????? String newpassword) throws Exception {
          ??????? if (isLogin()) {
          ??????????? DirectoryManager dm = new DirectoryManager();
          ??????????? String dn = dm.getUserDN(ConnParams.adminname);
          ??????????? dm.dirctx = dm.getDirectoryContext(dn, ConnParams.adminpassword);

          ??????????? return dm.changePassword(username, oldpassword, newpassword);
          ??????? } else {
          ??????????? return 0;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public int validUser(String name, String tag) throws Exception {
          ??????? if (isLogin()) {
          ??????????? DirectoryManager dm = new DirectoryManager();
          ??????????? String dn = dm.getUserDN(ConnParams.adminname);
          ??????????? dm.dirctx = dm.getDirectoryContext(dn, ConnParams.adminpassword);

          ??????????? return dm.validUser(name, tag);
          ??????? } else {
          ??????????? return 0;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public boolean searchAssembly(String name) throws Exception {
          ??????? if (isLogin()) {
          ??????????? DirectoryManager dm = new DirectoryManager();
          ??????????? String dn = dm.getUserDN(ConnParams.adminname);
          ??????????? dm.dirctx = dm.getDirectoryContext(dn, ConnParams.adminpassword);

          ??????????? String filter = "(" + ConnParams.RDN + "=" + name + ")";
          ??????????? list = dm.search(ConnParams.userctx, filter).iterator();

          ??????????? return true;
          ??????? } else {
          ??????????? return false;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public String searchNext() throws Exception {
          ??????? if (isLogin()) {
          ??????? try{
          ??????????? Attributes attrs = (Attributes) list.next();
          ??????????? String s = attrs.get(ConnParams.RDN).toString();

          ??????????? return s;
          ??????? }catch(Exception e)
          ??????? {
          ????????? return "The search result has been to end";
          ??????? }
          ??????? } else {
          ??????????? return "Loss Check Whether it's Authoricated";
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public boolean authenticateLogin(String username, String passwd)
          ??????? throws AuthenticationException, NamingException {
          ??????? if (username.equals("login_user") &&
          ??????????????? authenticateUser(username, passwd)) {
          ??????????? isLogin = true;

          ??????????? return true;
          ??????? } else {
          ??????????? return false;
          ??????? }
          ??? }

          ??? /**
          ???? *
          ???? * @webmethod
          ???? */
          ??? public boolean isLogin() {
          ??????? return isLogin;
          ??? }
          }

          UTIL BEAN:用于驗證EMAIL和LDAP密碼:

          package com.primesuccess.ldap;


          /**
          ?* The <code>ValidatorEx</code> provide these validators used in other class.
          ?* <p>
          ?*
          ?* @version 1.0
          ?* @author Kemi
          ?*/
          public class ValidatorEx {
          ??? /**
          ???? * Email格式驗證
          ???? * @param input 用戶輸入
          ???? * @return -1: Email輸入格式應該是一個字符串 <p>-2: "@"不存在或"@"不應該出現在首位<p> -3: "."分隔符號找不到或位置錯誤 <p> -4: "."不應該出現在末位 <p> 1: Email驗證成功
          ???? * @exception ValidationException 其他驗證異常
          ???? */
          ??? public static int doValidateEmail(Object input) {
          ??????? if (!(input instanceof String)) {
          ??????????? return -11;
          ??????? }

          ??????? String inputStr = (String) input;
          ??????? int idx = inputStr.indexOf(
          '@' );

          ??????? if ((idx == -1) || (idx == 0)) {
          ??????????? return -12;
          ??????? }

          ??????? int idx2 = inputStr.indexOf('.', idx);

          ??????? if ((idx2 == -1) || (idx2 == (idx + 1))) {
          ??????????? return -13;
          ??????? }

          ??????? if (inputStr.endsWith(".")) {
          ??????????? return -14;
          ??????? }

          ??????? return 1;
          ??? }

          ??? /**
          ??? * Password格式驗證
          ??? * @param input 用戶輸入
          ??? * @return -1: Password輸入格式應該是一個字符串<p> -2: Password至少應該包含一個數字 <p>-3: Password長度至少為5位 <p> 1: Password驗證成功
          ??? */
          ??? public static int doValidatePassword(Object input) {
          ??????? if (!(input instanceof String)) {
          ??????????? return -11;
          ??????? }

          ??????? String inputStr = (String) input;

          ??????? if ((inputStr.indexOf("0") == -1) && (inputStr.indexOf("1") == -1) &&
          ??????????????? (inputStr.indexOf("2") == -1) && (inputStr.indexOf("3") == -1) &&
          ??????????????? (inputStr.indexOf("4") == -1) && (inputStr.indexOf("5") == -1) &&
          ??????????????? (inputStr.indexOf("6") == -1) && (inputStr.indexOf("7") == -1) &&
          ??????????????? (inputStr.indexOf("8") == -1) && (inputStr.indexOf("0") == -1)) {
          ??????????? return -12;
          ??????? }

          ??????? if (inputStr.length() < 5) {
          ??????????? return -13;
          ??????? }

          ??????? return 1;
          ??? }
          }


          屬性文件

          #
          # File Name : Connection.properties
          # This file contains connection and configuration properties. Edit this file accordingly to your application server settings.
          #

          #
          #? The identity Management Realm is an area in Oracle Internet Direcotry where you
          #?? administer user identities and groups.
          #
          IDENTITY_MGMT_REALM=dc=dev,dc=daphne,dc=com,dc=cn
          #
          # HostName where Oracle Internet Directory is running
          #
          LDAP_HOST_NAME=oas.daphne.com.cn
          #
          # Port where Oracle Internet Directory is running
          #
          LDAP_PORT=389
          #
          # Data Source Name
          # The value of the ejb-location parameter of the Datasource used.
          # default:jdbc/GroceryStoreDS
          #
          DATASOURCE_NAME=jdbc/GroceryStoreDS
          LDAP_ADMIN_NAME=orcladmin
          LDAP_ADMIN_PASSWORD=abc123
          ldap_obj1=top
          ldap_obj2=person
          ldap_obj3=organizationalPerson
          ldap_obj4=inetOrgPerson
          ldap_obj5=orcluser
          ldap_obj6=orcluserV2
          ldap_userctx=cn=Users,dc=dev,dc=daphne,dc=com,dc=cn
          ldap_RDN=cn
          login_user=login_user

          posted on 2006-07-13 17:20 Kimi 閱讀(971) 評論(1)  編輯  收藏 所屬分類: Java

          評論

          # re: (原創) 用JAVA刺穿LDAP (二) 服務于WEB SERVICE [未登錄] 2012-03-20 09:59
          ContextNames  回復  更多評論
            

          主站蜘蛛池模板: 牡丹江市| 鹤岗市| 博野县| 清新县| 衡山县| 教育| 曲靖市| 安泽县| 福海县| 平罗县| 乡宁县| 莲花县| 虞城县| 新乡市| 元朗区| 镇宁| 延川县| 广西| 陇川县| 华宁县| 湘阴县| 光泽县| 新沂市| 阿拉善盟| 卢湾区| 海兴县| 四川省| 鲁甸县| 荣成市| 平遥县| 府谷县| 宁城县| 广昌县| 赤壁市| 年辖:市辖区| 出国| 松江区| 北碚区| 榆林市| 抚顺市| 安仁县|