📄 ldaploginmodule.java
字号:
package org.mortbay.jetty.plus.jaas.spi;// ========================================================================// Copyright 2007 Mort Bay Consulting Pty. Ltd.// ------------------------------------------------------------------------// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// ========================================================================import java.io.IOException;import java.util.ArrayList;import java.util.Hashtable;import java.util.List;import java.util.Map;import java.util.Properties;import javax.naming.Context;import javax.naming.NamingEnumeration;import javax.naming.NamingException;import javax.naming.directory.Attribute;import javax.naming.directory.Attributes;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;import javax.naming.directory.SearchControls;import javax.naming.directory.SearchResult;import javax.security.auth.Subject;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;import javax.security.auth.callback.NameCallback;import javax.security.auth.callback.UnsupportedCallbackException;import javax.security.auth.login.LoginException;import org.mortbay.jetty.plus.jaas.callback.ObjectCallback;import org.mortbay.jetty.security.Credential;import org.mortbay.log.Log;/** * * A LdapLoginModule for use with JAAS setups * * The jvm should be started with the following parameter: * <br><br> * <code> * -Djava.security.auth.login.config=etc/ldap-loginModule.conf * </code> * <br><br> * and an example of the ldap-loginModule.conf would be: * <br><br> * <pre> * ldaploginmodule { * org.mortbay.jetty.plus.jaas.spi.LdapLoginModule required * debug="true" * contextFactory="com.sun.jndi.ldap.LdapCtxFactory" * hostname="ldap.example.com" * port="389" * bindDn="cn=Directory Manager" * bindPassword="directory" * authenticationMethod="simple" * forceBindingLogin="false" * userBaseDn="ou=people,dc=alcatel" * userRdnAttribute="uid" * userIdAttribute="uid" * userPasswordAttribute="userPassword" * userObjectClass="inetOrgPerson" * roleBaseDn="ou=groups,dc=example,dc=com" * roleNameAttribute="cn" * roleMemberAttribute="uniqueMember" * roleObjectClass="groupOfUniqueNames"; * }; * </pre> * * @author Jesse McConnell <jesse@codehaus.org> * @author Frederic Nizery <frederic.nizery@alcatel-lucent.fr> * @author Trygve Laugstol <trygvis@codehaus.org> */public class LdapLoginModule extends AbstractLoginModule{ /** * hostname of the ldap server */ private String _hostname; /** * port of the ldap server */ private int _port; /** * Context.SECURITY_AUTHENTICATION */ private String _authenticationMethod; /** * Context.INITIAL_CONTEXT_FACTORY */ private String _contextFactory; /** * root DN used to connect to */ private String _bindDn; /** * password used to connect to the root ldap context */ private String _bindPassword; /** * object class of a user */ private String _userObjectClass = "inetOrgPerson"; /** * attribute that the principal is located */ private String _userRdnAttribute = "uid"; /** * attribute that the principal is located */ private String _userIdAttribute = "cn"; /** * name of the attribute that a users password is stored under * <p/> * NOTE: not always accessible, see force binding login */ private String _userPasswordAttribute = "userPassword"; /** * base DN where users are to be searched from */ private String _userBaseDn; /** * base DN where role membership is to be searched from */ private String _roleBaseDn; /** * object class of roles */ private String _roleObjectClass = "groupOfUniqueNames"; /** * name of the attribute that a username would be under a role class */ private String _roleMemberAttribute = "uniqueMember"; /** * the name of the attribute that a role would be stored under */ private String _roleNameAttribute = "roleName"; private boolean _debug; /** * if the getUserInfo can pull a password off of the user then * password comparison is an option for authn, to force binding * login checks, set this to true */ private boolean _forceBindingLogin = false; private DirContext _rootContext; /** * get the available information about the user * <p/> * for this LoginModule, the credential can be null which will result in a * binding ldap authentication scenario * <p/> * roles are also an optional concept if required * * @param username * @return * @throws Exception */ public UserInfo getUserInfo(String username) throws Exception { String pwdCredential = getUserCredentials(username); if (pwdCredential == null) { return null; } pwdCredential = convertCredentialLdapToJetty(pwdCredential); //String md5Credential = Credential.MD5.digest("foo"); //byte[] ba = digestMD5("foo"); //System.out.println(md5Credential + " " + ba ); Credential credential = Credential.getCredential(pwdCredential); List roles = getUserRoles(_rootContext, username); return new UserInfo(username, credential, roles); } protected String doRFC2254Encoding(String inputString) { StringBuffer buf = new StringBuffer(inputString.length()); for (int i = 0; i < inputString.length(); i++) { char c = inputString.charAt(i); switch (c) { case '\\': buf.append("\\5c"); break; case '*': buf.append("\\2a"); break; case '(': buf.append("\\28"); break; case ')': buf.append("\\29"); break; case '\0': buf.append("\\00"); break; default: buf.append(c); break; } } return buf.toString(); } /** * attempts to get the users credentials from the users context * <p/> * NOTE: this is not an user authenticated operation * * @param username * @return * @throws LoginException */ private String getUserCredentials(String username) throws LoginException { String ldapCredential = null; SearchControls ctls = new SearchControls(); ctls.setCountLimit(1); ctls.setDerefLinkFlag(true); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(&(objectClass={0})({1}={2}))"; Log.debug("Searching for users with filter: \'" + filter + "\'" + " from base dn: " + _userBaseDn); try { Object[] filterArguments = {_userObjectClass, _userIdAttribute, username}; NamingEnumeration results = _rootContext.search(_userBaseDn, filter, filterArguments, ctls); Log.debug("Found user?: " + results.hasMoreElements()); if (!results.hasMoreElements()) { throw new LoginException("User not found."); } SearchResult result = findUser(username); Attributes attributes = result.getAttributes(); Attribute attribute = attributes.get(_userPasswordAttribute); if (attribute != null) { try { byte[] value = (byte[]) attribute.get(); ldapCredential = new String(value); } catch (NamingException e) { Log.debug("no password available under attribute: " + _userPasswordAttribute); } } } catch (NamingException e) { throw new LoginException("Root context binding failure."); } Log.debug("user cred is: " + ldapCredential); return ldapCredential; } /** * attempts to get the users roles from the root context * <p/> * NOTE: this is not an user authenticated operation * * @param dirContext * @param username * @return * @throws LoginException */ private List getUserRoles(DirContext dirContext, String username) throws LoginException, NamingException { String userDn = _userRdnAttribute + "=" + username + "," + _userBaseDn; return getUserRolesByDn(dirContext, userDn); } private List getUserRolesByDn(DirContext dirContext, String userDn) throws LoginException, NamingException { ArrayList roleList = new ArrayList(); if (dirContext == null || _roleBaseDn == null || _roleMemberAttribute == null || _roleObjectClass == null) { return roleList; } SearchControls ctls = new SearchControls(); ctls.setDerefLinkFlag(true); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(&(objectClass={0})({1}={2}))"; Object[] filterArguments = {_roleObjectClass, _roleMemberAttribute, userDn}; NamingEnumeration results = dirContext.search(_roleBaseDn, filter, filterArguments, ctls); Log.debug("Found user roles?: " + results.hasMoreElements()); while (results.hasMoreElements()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -