logincontext.java

来自「java jdk 1.4的源码」· Java 代码 · 共 840 行 · 第 1/3 页

JAVA
840
字号
/* * @(#)LoginContext.java	1.94 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package javax.security.auth.login;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.lang.reflect.InvocationTargetException;import java.util.LinkedList;import java.util.Map;import java.util.HashMap;import java.text.MessageFormat;import javax.security.auth.Subject;import javax.security.auth.AuthPermission;import javax.security.auth.callback.*;import java.security.AccessController;import java.security.AccessControlContext;import sun.security.util.ResourcesMgr;/** * <p> The <code>LoginContext</code> class describes the basic methods used * to authenticate Subjects and provides a way to develop an * application independent of the underlying authentication technology. * A <code>Configuration</code> specifies the authentication technology, or * <code>LoginModule</code>, to be used with a particular application. * Therefore, different LoginModules can be plugged in under an application * without requiring any modifications to the application itself. * * <p> In addition to supporting <i>pluggable</i> authentication, this class * also supports the notion of <i>stacked</i> authentication.  In other words, * an application may be configured to use more than one * <code>LoginModule</code>.  For example, one could * configure both a Kerberos <code>LoginModule</code> and a smart card * <code>LoginModule</code> under an application. * * <p> A typical caller instantiates this class and passes in * a <i>name</i> and a <code>CallbackHandler</code>. * <code>LoginContext</code> uses the <i>name</i> as the index into the * <code>Configuration</code> to determine which LoginModules should be used, * and which ones must succeed in order for the overall authentication to * succeed.  The <code>CallbackHandler</code> is passed to the underlying * LoginModules so they may communicate and interact with users * (prompting for a username and password via a graphical user interface, * for example). * * <p> Once the caller has instantiated a <code>LoginContext</code>, * it invokes the <code>login</code> method to authenticate * a <code>Subject</code>.  This <code>login</code> method invokes the * <code>login</code> method from each of the LoginModules configured for * the <i>name</i> specified by the caller.  Each <code>LoginModule</code> * then performs its respective type of authentication (username/password, * smart card pin verification, etc.).  Note that the LoginModules will not * attempt authentication retries or introduce delays if the authentication * fails.  Such tasks belong to the caller. * * <p> Regardless of whether or not the overall authentication succeeded, * this <code>login</code> method completes a 2-phase authentication process * by then calling either the <code>commit</code> method or the * <code>abort</code> method for each of the configured LoginModules. * The <code>commit</code> method for each <code>LoginModule</code> * gets invoked if the overall authentication succeeded, * whereas the <code>abort</code> method for each <code>LoginModule</code> * gets invoked if the overall authentication failed. * Each successful LoginModule's <code>commit</code> * method associates the relevant Principals (authenticated identities) * and Credentials (authentication data such as cryptographic keys) * with the <code>Subject</code>.  Each LoginModule's <code>abort</code> * method cleans up or removes/destroys any previously stored authentication * state. * * <p> If the <code>login</code> method returns without * throwing an exception, then the overall authentication succeeded. * The caller can then retrieve * the newly authenticated <code>Subject</code> by invoking the * <code>getSubject</code> method.  Principals and Credentials associated * with the <code>Subject</code> may be retrieved by invoking the Subject's * respective <code>getPrincipals</code>, <code>getPublicCredentials</code>, * and <code>getPrivateCredentials</code> methods. * * <p> To logout the <code>Subject</code>, the caller simply needs to * invoke the <code>logout</code> method.  As with the <code>login</code> * method, this <code>logout</code> method invokes the <code>logout</code> * method for each <code>LoginModule</code> configured for this * <code>LoginContext</code>.  Each LoginModule's <code>logout</code> * method cleans up state and removes/destroys Principals and Credentials * from the <code>Subject</code> as appropriate. *  * <p> Each of the configured LoginModules invoked by the * <code>LoginContext</code> is initialized with a * <code>Subject</code> to be authenticated, a <code>CallbackHandler</code> * used to communicate with users, shared <code>LoginModule</code> state, * and LoginModule-specific options.  If the <code>LoginContext</code> * was not provided a <code>Subject</code> then it instantiates one itself. * * <p> Each <code>LoginModule</code> * which successfully authenticates a user updates the <code>Subject</code> * with the relevant user information (Principals and Credentials). * This <code>Subject</code> can then be returned via the * <code>getSubject</code> method from the <code>LoginContext</code> class * if the overall authentication succeeds.  Note that LoginModules are always * invoked from within an <code>AccessController.doPrivileged</code> call. * Therefore, although LoginModules that perform security-sensitive tasks * (such as connecting to remote hosts) need to be granted the relevant * Permissions in the security <code>Policy</code>, the callers of the * LoginModules do not require those Permissions. *  * <p> A <code>LoginContext</code> supports authentication retries  * by the calling application.  For example, a LoginContext's * <code>login</code> method may be invoked multiple times * if the user incorrectly types in a password.  However, a * <code>LoginContext</code> should not be used to authenticate * more than one <code>Subject</code>.  A separate <code>LoginContext</code> * should be used to authenticate each different <code>Subject</code>. *  * <p> Multiple calls into the same <code>LoginContext</code>  * do not affect the <code>LoginModule</code> state, or the * LoginModule-specific options. *  * @version 1.94, 01/23/03 * @see javax.security.auth.Subject * @see javax.security.auth.callback.CallbackHandler * @see javax.security.auth.login.Configuration * @see javax.security.auth.spi.LoginModule */public class LoginContext {    private static final String INIT_METHOD		= "initialize";    private static final String LOGIN_METHOD		= "login";    private static final String COMMIT_METHOD		= "commit";    private static final String ABORT_METHOD		= "abort";    private static final String LOGOUT_METHOD		= "logout";    private static final String OTHER			= "other";    private static final String DEFAULT_HANDLER		=				"auth.login.defaultCallbackHandler";    private Subject subject = null;    private boolean subjectProvided = false;    private boolean loginSucceeded = false;    private CallbackHandler callbackHandler;    private Map state = new HashMap();    private Configuration config;    private ModuleInfo[] moduleStack;    private ClassLoader contextClassLoader = null;    private static final Class[] PARAMS = { };    private static final sun.security.util.Debug debug =	sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]");    private void init(String name) throws LoginException {	java.lang.SecurityManager sm = System.getSecurityManager();	if (sm != null) {	    sm.checkPermission(new AuthPermission				("createLoginContext." + name));	}	if (name == null)	    throw new LoginException		(ResourcesMgr.getString("Invalid null input: name"));	// get the Configuration	if (config == null) {	    config = (Configuration)java.security.AccessController.doPrivileged		(new java.security.PrivilegedAction() {		public Object run() {			    return Configuration.getConfiguration();		}	    });	}	// get the LoginModules configured for this application	AppConfigurationEntry[] entries = config.getAppConfigurationEntry(name);	if (entries == null) {	    if (sm != null) {		sm.checkPermission(new AuthPermission				("createLoginContext." + OTHER));	    }	    entries = config.getAppConfigurationEntry(OTHER);	    if (entries == null) {		MessageFormat form = new MessageFormat(ResourcesMgr.getString			("No LoginModules configured for name"));		Object[] source = {name};		throw new LoginException(form.format(source));	    }	}	moduleStack = new ModuleInfo[entries.length];	for (int i = 0; i < entries.length; i++) {	    // clone returned array	    moduleStack[i] = new ModuleInfo				(new AppConfigurationEntry					(entries[i].getLoginModuleName(),					entries[i].getControlFlag(),					entries[i].getOptions()),				null);	}	contextClassLoader =		(ClassLoader)java.security.AccessController.doPrivileged		(new java.security.PrivilegedAction() {		public Object run() {			    return Thread.currentThread().getContextClassLoader();		}	});    }    private void loadDefaultCallbackHandler() throws LoginException {	// get the default handler class	try {	    final ClassLoader finalLoader = contextClassLoader;	    this.callbackHandler = (CallbackHandler)		java.security.AccessController.doPrivileged		(new java.security.PrivilegedExceptionAction() {		public Object run() throws Exception {		    String defaultHandler = java.security.Security.getProperty			("auth.login.defaultCallbackHandler");		    if (defaultHandler == null || defaultHandler.length() == 0)			return null;		    Class c = Class.forName(defaultHandler,					true,					finalLoader);		    return c.newInstance();		}	    });	} catch (java.security.PrivilegedActionException pae) {	    throw new LoginException(pae.getException().toString());	}	// secure it with the caller's ACC	if (this.callbackHandler != null) {	    this.callbackHandler = new SecureCallbackHandler				(java.security.AccessController.getContext(),				this.callbackHandler);	}    }    /**     * Constructor for the <code>LoginContext</code> class.     *     * <p> Initialize the new <code>LoginContext</code> object with a name.     * <code>LoginContext</code> uses the specified name as the index     * into the <code>Configuration</code> to determine which LoginModules     * should be used.  If the provided name does not match any in the     * <code>Configuration</code>, then the <code>LoginContext</code>     * uses the default <code>Configuration</code> entry, "<i>other</i>".     * If there is no <code>Configuration</code> entry for "<i>other</i>",     * then a <code>LoginException</code> is thrown.     *     * <p> This constructor does not allow for a <code>CallbackHandler</code>.     * If the <i>auth.login.defaultCallbackHandler</i> security property     * is set to the fully qualified name of a default     * <code>CallbackHandler</code> implementation class,     * then that <code>CallbackHandler</code> will be loaded and     * passed to the underlying LoginModules.  If the security property     * is not set, then the underlying LoginModules     * will not have a <code>CallbackHandler</code> for use in communicating     * with users.  The caller thus assumes that the configured     * LoginModules have alternative means for authenticating the user.     *     * <p> The <i>auth.login.defaultCallbackHandler</i> security property     * can be set in the Java security properties file located in the     * file named &lt;JAVA_HOME&gt;/lib/security/java.security,     * where &lt;JAVA_HOME&gt; refers to the directory where the SDK     * was installed.     *     * <p> Since no <code>Subject</code> can be specified to this constructor,     * it instantiates a <code>Subject</code> itself.     *     * <p>     *     * @param name the name used as the index into the

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?