jndiloginmodule.java

来自「JAVA 所有包」· Java 代码 · 共 752 行 · 第 1/2 页

JAVA
752
字号
	    if (debug) {		System.out.println("\t\t[JndiLoginModule]: " +				   "added UnixPrincipal,");		System.out.println("\t\t\t\tUnixNumericUserPrincipal,");		System.out.println("\t\t\t\tUnixNumericGroupPrincipal(s),");		System.out.println("\t\t\t to Subject");	    }	}	// in any case, clean out state	cleanState();	commitSucceeded = true;	return true;    }    /**     * <p> This method is called if the LoginContext's     * overall authentication failed.     * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules     * did not succeed).     *     * <p> If this LoginModule's own authentication attempt     * succeeded (checked by retrieving the private state saved by the     * <code>login</code> and <code>commit</code> methods),     * then this method cleans up any state that was originally saved.     *     * <p>     *     * @exception LoginException if the abort fails.     *     * @return false if this LoginModule's own login and/or commit attempts     *		failed, and true otherwise.     */    public boolean abort() throws LoginException {	if (debug)	    System.out.println("\t\t[JndiLoginModule]: " +		"aborted authentication failed");	if (succeeded == false) {	    return false;	} else if (succeeded == true && commitSucceeded == false) {	    // Clean out state	    succeeded = false;	    cleanState();	    userPrincipal = null;	    UIDPrincipal = null;	    GIDPrincipal = null;	    supplementaryGroups = new LinkedList();	} else {	    // overall authentication succeeded and commit succeeded,	    // but someone else's commit failed	    logout();	}	return true;    }    /**     * Logout a user.     *     * <p> This method removes the Principals     * that were added by the <code>commit</code> method.     *     * <p>     *     * @exception LoginException if the logout fails.     *     * @return true in all cases since this <code>LoginModule</code>     *		should not be ignored.     */    public boolean logout() throws LoginException {	if (subject.isReadOnly()) {	    cleanState();	    throw new LoginException ("Subject is Readonly");	}	subject.getPrincipals().remove(userPrincipal);	subject.getPrincipals().remove(UIDPrincipal);	subject.getPrincipals().remove(GIDPrincipal);	for (int i = 0; i < supplementaryGroups.size(); i++) {	    subject.getPrincipals().remove		((UnixNumericGroupPrincipal)supplementaryGroups.get(i));	}        	// clean out state	cleanState();	succeeded = false;	commitSucceeded = false;	userPrincipal = null;	UIDPrincipal = null;	GIDPrincipal = null;	supplementaryGroups = new LinkedList();	if (debug) {	    System.out.println("\t\t[JndiLoginModule]: " +		"logged out Subject");	}	return true;    }    /**     * Attempt authentication     *     * <p>     *     * @param getPasswdFromSharedState boolean that tells this method whether     *		to retrieve the password from the sharedState.     */    private void attemptAuthentication(boolean getPasswdFromSharedState)    throws LoginException {	String encryptedPassword = null;	// first get the username and password	getUsernamePassword(getPasswdFromSharedState);		try {	    // get the user's passwd entry from the user provider URL	    InitialContext iCtx = new InitialContext();	    ctx = (DirContext)iCtx.lookup(userProvider);	    /*	    SearchControls controls = new SearchControls					(SearchControls.ONELEVEL_SCOPE,					0,					5000,					new String[] { USER_PWD },					false,					false);	    */	    SearchControls controls = new SearchControls();	    NamingEnumeration ne = ctx.search("",					"(uid=" + username + ")",					controls);	    if (ne.hasMore()) {		SearchResult result = (SearchResult)ne.next();		Attributes attributes = result.getAttributes();		// get the password		// this module works only if the LDAP directory server		// is configured to permit read access to the userPassword		// attribute. The directory administrator need to grant		// this access.		//		// A workaround would be to make the server do authentication		// by setting the Context.SECURITY_PRINCIPAL		// and Context.SECURITY_CREDENTIALS property.		// However, this would make it not work with systems that		// don't do authentication at the server (like NIS).		//		// Setting the SECURITY_* properties and using "simple"		// authentication for LDAP is recommended only for secure		// channels. For nonsecure channels, SSL is recommended.		Attribute pwd = attributes.get(USER_PWD);		String encryptedPwd = new String((byte[])pwd.get(), "UTF8");		encryptedPassword = encryptedPwd.substring(CRYPT.length());		// check the password		if (verifyPassword		    (encryptedPassword, new String(password)) == true) {		    // authentication succeeded		    if (debug)			System.out.println("\t\t[JndiLoginModule] " +				"attemptAuthentication() succeeded");		} else {		    // authentication failed		    if (debug)			System.out.println("\t\t[JndiLoginModule] " +				"attemptAuthentication() failed");		    throw new FailedLoginException("Login incorrect");		}		// save input as shared state only if		// authentication succeeded		if (storePass &&		    !sharedState.containsKey(NAME) &&		    !sharedState.containsKey(PWD)) {		    sharedState.put(NAME, username);		    sharedState.put(PWD, password);		}		// create the user principal		userPrincipal = new UnixPrincipal(username);		// get the UID		Attribute uid = attributes.get(USER_UID);		String uidNumber = (String)uid.get();		UIDPrincipal = new UnixNumericUserPrincipal(uidNumber);		if (debug && uidNumber != null) {		    System.out.println("\t\t[JndiLoginModule] " +				"user: '" + username + "' has UID: " +				uidNumber);		}		// get the GID		Attribute gid = attributes.get(USER_GID);		String gidNumber = (String)gid.get();		GIDPrincipal = new UnixNumericGroupPrincipal				(gidNumber, true);		if (debug && gidNumber != null) {		    System.out.println("\t\t[JndiLoginModule] " +				"user: '" + username + "' has GID: " +				gidNumber);		}		// get the supplementary groups from the group provider URL		ctx = (DirContext)iCtx.lookup(groupProvider);		ne = ctx.search("", new BasicAttributes("memberUid", username));		while (ne.hasMore()) {		    result = (SearchResult)ne.next();		    attributes = result.getAttributes();		    gid = attributes.get(GROUP_ID);		    String suppGid = (String)gid.get();		    if (!gidNumber.equals(suppGid)) {			UnixNumericGroupPrincipal suppPrincipal =			    new UnixNumericGroupPrincipal(suppGid, false);			supplementaryGroups.add(suppPrincipal);			if (debug && suppGid != null) {			    System.out.println("\t\t[JndiLoginModule] " +				"user: '" + username +				"' has Supplementary Group: " +				suppGid);			}		    }		}	    } else {		// bad username		if (debug) {		    System.out.println("\t\t[JndiLoginModule]: User not found");		}		throw new FailedLoginException("User not found");	    }	} catch (NamingException ne) {	    // bad username	    if (debug) {		System.out.println("\t\t[JndiLoginModule]:  User not found");		ne.printStackTrace();	    }	    throw new FailedLoginException("User not found");	} catch (java.io.UnsupportedEncodingException uee) {	    // password stored in incorrect format	    if (debug) {		System.out.println("\t\t[JndiLoginModule]:  " +				"password incorrectly encoded");		uee.printStackTrace();	    }	    throw new LoginException("Login failure due to incorrect " +				"password encoding in the password database");	}	// authentication succeeded    }     /**     * Get the username and password.     * This method does not return any value.     * Instead, it sets global name and password variables.     *     * <p> Also note that this method will set the username and password     * values in the shared state in case subsequent LoginModules     * want to use them via use/tryFirstPass.     *     * <p>     *     * @param getPasswdFromSharedState boolean that tells this method whether     *		to retrieve the password from the sharedState.     */    private void getUsernamePassword(boolean getPasswdFromSharedState)    throws LoginException {	if (getPasswdFromSharedState) {	    // use the password saved by the first module in the stack	    username = (String)sharedState.get(NAME);	    password = (char[])sharedState.get(PWD);	    return;	}	// prompt for a username and password        if (callbackHandler == null)	    throw new LoginException("Error: no CallbackHandler available " +		"to garner authentication information from the user");	String protocol = userProvider.substring(0, userProvider.indexOf(":"));	Callback[] callbacks = new Callback[2];	callbacks[0] = new NameCallback(protocol + " " 					    + rb.getString("username: "));	callbacks[1] = new PasswordCallback(protocol + " " + 					        rb.getString("password: "),					    false);	try {	    callbackHandler.handle(callbacks);	    username = ((NameCallback)callbacks[0]).getName();	    char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();	    password = new char[tmpPassword.length];	    System.arraycopy(tmpPassword, 0,				password, 0, tmpPassword.length);	    ((PasswordCallback)callbacks[1]).clearPassword();	} catch (java.io.IOException ioe) {	    throw new LoginException(ioe.toString());	} catch (UnsupportedCallbackException uce) {	    throw new LoginException("Error: " + uce.getCallback().toString() +			" not available to garner authentication information " +			"from the user");	}	// print debugging information	if (strongDebug) {	    System.out.println("\t\t[JndiLoginModule] " +				"user entered username: " +				username);	    System.out.print("\t\t[JndiLoginModule] " +				"user entered password: ");	    for (int i = 0; i < password.length; i++)		System.out.print(password[i]);	    System.out.println();	}    }    /**     * Verify a password against the encrypted passwd from /etc/shadow     */    private boolean verifyPassword(String encryptedPassword, String password) {	if (encryptedPassword == null)	    return false;	Crypt c = new Crypt();	try {	    byte oldCrypt[] = encryptedPassword.getBytes("UTF8");	    byte newCrypt[] = c.crypt(password.getBytes("UTF8"),				      oldCrypt);	    if (newCrypt.length != oldCrypt.length)	        return false;	    for (int i = 0; i < newCrypt.length; i++) {	        if (oldCrypt[i] != newCrypt[i])		    return false;	    }	} catch (java.io.UnsupportedEncodingException uee) {	    // cannot happen, but return false just to be safe	    return false;	}	return true;    }    /**     * Clean out state because of a failed authentication attempt     */    private void cleanState() {	username = null;	if (password != null) {	    for (int i = 0; i < password.length; i++)		password[i] = ' ';	    password = null;	}	ctx = null;	if (clearPass) {	    sharedState.remove(NAME);	    sharedState.remove(PWD);	}    }}

⌨️ 快捷键说明

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