📄 ldapconnection.java
字号:
/* * LDAPConnection.java * Copyright (C) 2004 The Free Software Foundation * * This file is part of GNU inetlib, a library. * * GNU inetlib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU inetlib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obliged to do so. If you do not wish to do so, delete this * exception statement from your version. */package gnu.inet.ldap;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.InputStream;import java.io.IOException;import java.io.OutputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.net.InetSocketAddress;import java.net.ProtocolException;import java.net.Socket;import java.net.SocketAddress;import java.util.ArrayList;import javax.naming.ldap.Control;/** * An LDAPv3 client. * This client is still experimental, please contact * <a href='mailto:dog@gnu.org'>Chris Burdess</a> if you want to help out * with it. * * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> */public class LDAPConnection{ /** * The default LDAP port. */ public static final int DEFAULT_PORT = 389; public static final int SCOPE_BASE_OBJECT = 0; public static final int SCOPE_SINGLE_LEVEL = 1; public static final int SCOPE_WHOLE_SUBTREE = 2; /** * Do not dereference aliases in searching or in locating the base object * of the search. */ public static final int DEREF_NEVER = 0; /** * Dereference aliases in subordinates of the base object in searching, * but not in locating the base object of the search. */ public static final int DEREF_IN_SEARCHING = 1; /** * Dereference aliases in locating the base object of the search, but not * when searching subordinates of the base object. */ public static final int DEREF_FINDING_BASE_OBJ = 2; /** * Dereference aliases both in searching and in locating the base object * of the search. */ public static final int DEREF_ALWAYS = 3; private static final int SUCCESS = 0; private static final int SASL_BIND_IN_PROGRESS = 14; private static final int MESSAGE = 0x30; private static final int BIND_REQUEST = 0x60; private static final int BIND_RESPONSE = 0x61; private static final int UNBIND_REQUEST = 0x62; private static final int SEARCH_REQUEST = 0x63; private static final int SEARCH_RESULT = 0x64; private static final int SEARCH_RESULT_DONE = 0x65; private static final int MODIFY_REQUEST = 0x66; private static final int MODIFY_RESPONSE = 0x67; private static final int ADD_REQUEST = 0x68; private static final int ADD_RESPONSE = 0x69; private static final int DELETE_REQUEST = 0x6a; private static final int DELETE_RESPONSE = 0x6b; private static final int MODIFY_DN_REQUEST = 0x6c; private static final int MODIFY_DN_RESPONSE = 0x6d; private static final int SEARCH_REFERENCE = 0x73; protected String host; protected int port; protected int version; // 2 or 3 private Socket socket; private InputStream in; private OutputStream out; private int messageId; private Map asyncResponses; /** * Creates a new LDAP connection to the specified host, using the default * LDAP port. * @param host the host */ public LDAPConnection(String host) throws IOException { this(host, DEFAULT_PORT, 0, 0); } /** * Creates a new LDAP connection to the specified host and port. * @param host the host * @param port the port */ public LDAPConnection(String host, int port) throws IOException { this(host, port, 0, 0); } /** * Creates a new LDAP connection to the specified host, port, and timeouts. * @param host the host * @param port the port * @param connectionTimeout the connection timeout in ms * @param timeout the socket I/O timeout in ms */ public LDAPConnection(String host, int port, int connectionTimeout, int timeout) throws IOException { this.host = host; if (port < 0) { port = DEFAULT_PORT; } this.port = port; messageId = 0; asyncResponses = new HashMap(); version = 3; // Connect socket = new Socket(); SocketAddress address = new InetSocketAddress(host, port); if (connectionTimeout > 0) { socket.connect(address, connectionTimeout); } else { socket.connect(address); } in = new BufferedInputStream(socket.getInputStream()); out = new BufferedOutputStream(socket.getOutputStream()); } /** * Sets the version of LDAP to use. * This implementation supports versions 2 and 3. * @param version the LDAP version */ public void setVersion(int version) { if (version < 2 || version > 3) { throw new IllegalArgumentException(Integer.toString(version)); } this.version = version; } /** * Initiates a bind operation to authenticate the client to the server. * @param name the LDAP DN to authenticate to, or <code>null</code> for * anonymous binding * @param mechanism the SASL mechanism to use, or <code>null</code> for * simple authentication * @param credentials the security credentials to use * @return the LDAP result */ public LDAPResult bind(String name, String mechanism, byte[] credentials, Control[] controls) throws IOException { int id = messageId++; boolean utf8 = (version == 3); BEREncoder bind = new BEREncoder(utf8); if (mechanism == null) { bind.append(version); bind.append(name); if (credentials != null) { bind.append(credentials); } } else { bind.append(version); bind.append(name); // SASL credentials BEREncoder saslCredentials = new BEREncoder(utf8); saslCredentials.append(mechanism); if (credentials != null) { saslCredentials.append(credentials); } bind.append(saslCredentials.toByteArray(), BERConstants.SEQUENCE); } // Request controls BEREncoder ctls = new BEREncoder(utf8); if (controls != null) { for (int i = 0; i < controls.length; i++) { ctls.append(controlSequence(controls[i], utf8), BERConstants.SEQUENCE); } } bind.append(ctls.toByteArray(), BERConstants.CONTEXT); // Write request write(id, BIND_REQUEST, bind.toByteArray()); // Read response BERDecoder response = read(id); BERDecoder resultSequence = response.parseSequence(BIND_RESPONSE); LDAPResult result = parseResult(resultSequence); if (resultSequence.available()) { byte[] serverCreds = resultSequence.parseOctetString(); // TODO } // TODO response controls return result; } /** * Issues an unbind request. This indicates to the server that the client * has no more requests to issue and will terminate the connection. After * invoking this method, no further methods may be invoked. */ public void unbind() throws IOException { int id = messageId++; boolean utf8 = (version == 3); BEREncoder unbind = new BEREncoder(utf8); unbind.appendNull(); write(id, UNBIND_REQUEST, unbind.toByteArray()); // Close socket socket.close(); } /** * Issues a search request. * @param name the LDAP DN that is the base object entry relative to which * the search is to be performed * @param scope the search scope, one of the SCOPE_* constants * @param derefAliases whether to dereference aliases, one of the DEREF_* * constants * @param sizeLimit the maximum number of entries to return, or 0 for no * restriction * @param timeLimit the maximum time in seconds permitted for the search, * or 0 for no restriction * @param typesOnly whether to return only attribute types(true) or both * attribute types and values(false) * @param filter the search filter in RFC2254 format * @param attributes the IDs of the attributes to return * @param controls the request controls * @param handler the result handler to receive notification of results * @return the LDAP result */ public LDAPResult search(String name, int scope, int derefAliases, int sizeLimit, int timeLimit, boolean typesOnly, String filter, String[] attributes, Control[] controls, ResultHandler handler) throws IOException { if (filter == null || filter.length() == 0) { filter = "(objectClass=*)"; } int id = messageId++; boolean utf8 = (version == 3); BEREncoder search = new BEREncoder(utf8); search.append(name); search.append(scope, BERConstants.ENUMERATED); search.append(derefAliases, BERConstants.ENUMERATED); search.append(sizeLimit); search.append(timeLimit); search.append(typesOnly); search.appendFilter(filter); BEREncoder attributeSequence = new BEREncoder(utf8); if (attributes != null) { for (int i = 0; i < attributes.length; i++) { attributeSequence.append(attributes[i]); } } search.append(attributeSequence.toByteArray(), BERConstants.SEQUENCE); // Request controls BEREncoder ctls = new BEREncoder(utf8); if (controls != null) { for (int i = 0; i < controls.length; i++) { ctls.append(controlSequence(controls[i], utf8), BERConstants.SEQUENCE); } } search.append(ctls.toByteArray(), BERConstants.SEQUENCE); // Write request write(id, SEARCH_REQUEST, search.toByteArray()); do { BERDecoder response = read(id); int code = response.parseType(); switch (code) { case SEARCH_RESULT: BERDecoder entry = response.parseSequence(code); String objectName = entry.parseString(); BERDecoder attributeSeq = entry.parseSequence(0x30); Map attrs = new TreeMap(); while (attributeSeq.available()) { BERDecoder attribute = attributeSeq.parseSequence(0x30); String type = attribute.parseString(); BERDecoder values = attribute.parseSet(0x31); List acc = new ArrayList(); while (values.available()) { int valueType = values.parseType(); switch (valueType) { case BERConstants.BOOLEAN: acc.add(Boolean.valueOf(values.parseBoolean())); break; case BERConstants.INTEGER: case BERConstants.ENUMERATED: acc.add(new Integer(values.parseInt())); break; // TODO float case BERConstants.UTF8_STRING: acc.add(values.parseString()); break; case BERConstants.OCTET_STRING: acc.add(values.parseOctetString()); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -