Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
 package org.jboss.security.auth.spi;
 
 import java.util.Map;
 
 
An abstract subclass of AbstractServerLoginModule that imposes an identity == String username, credentials == String password view on the login process.

Subclasses override the getUsersPassword() and getRoleSets() methods to return the expected password and roles for the user.

 
 public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule
 {
   
The login identity
 
    private Principal identity;
   
The proof of login identity
 
    private char[] credential;
   
the message digest algorithm used to hash passwords. If null then plain passwords will be used.
 
    private String hashAlgorithm = null;
  
the name of the charset/encoding to use when converting the password String to a byte array. Default is the platform's default encoding.
 
    private String hashCharset = null;
   
the string encoding format to use. Defaults to base64.
 
    private String hashEncoding = null;
   
A flag indicating if the password comparison should ignore case
 
    private boolean ignorePasswordCase;
   
A flag indicating if the store password should be hashed using the hashAlgorithm
 
    private boolean hashStorePassword;

   
A flag indicating if the user inputted password should be hashed using the hashAlgorithm
 
    private boolean hashUserPassword = true;
   
A flag that restores the ability to override the createPasswordHash(String,String)
 
    private boolean legacyCreatePasswordHash;
   
 
    private Throwable validateError

   
Override the superclass method to look for the following options after first invoking the super version.

Parameters:
options : option: hashAlgorithm - the message digest algorithm used to hash passwords. If null then plain passwords will be used. option: hashCharset - the name of the charset/encoding to use when converting the password String to a byte array. Default is the platform's default encoding. option: hashEncoding - the string encoding format to use. Defaults to base64. option: ignorePasswordCase: A flag indicating if the password comparison should ignore case. option: digestCallback - The class name of the DigestCallback org.jboss.crypto.digest.DigestCallback implementation that includes pre/post digest content like salts for hashing the input password. Only used if hashAlgorithm has been specified. option: hashStorePassword - A flag indicating if the store password returned from #getUsersPassword() should be hashed . option: hashUserPassword - A flag indicating if the user entered password should be hashed. option: storeDigestCallback - The class name of the DigestCallback org.jboss.crypto.digest.DigestCallback implementation that includes pre/post digest content like salts for hashing the store/expected password. Only used if hashStorePassword or hashUserPassword is true and hashAlgorithm has been specified.
   public void initialize(Subject subjectCallbackHandler callbackHandler,
      Map<String,?> sharedStateMap<String,?> options)
   {
      super.initialize(subjectcallbackHandlersharedStateoptions);
      // Check to see if password hashing has been enabled.
      // If an algorithm is set, check for a format and charset.
       = (Stringoptions.get("hashAlgorithm");
      if != null )
      {
          = (Stringoptions.get("hashEncoding");
         if == null )
             = .;
          = (Stringoptions.get("hashCharset");
         if.isTraceEnabled() )
         {
            .trace("Password hashing activated: algorithm = " + 
               + ", encoding = " + 
               + ", charset = " + ( == null ? "{default}" : )
               + ", callback = " + options.get("digestCallback")
               + ", storeCallback = " + options.get("storeDigestCallback")
            );
         }
      }
      String flag = (Stringoptions.get("ignorePasswordCase");
       = Boolean.valueOf(flag).booleanValue();
      flag = (Stringoptions.get("hashStorePassword");
       = Boolean.valueOf(flag).booleanValue();
      flag = (Stringoptions.get("hashUserPassword");
      ifflag != null )
          = Boolean.valueOf(flag).booleanValue();
      flag = (Stringoptions.get("legacyCreatePasswordHash");
      ifflag != null )
          = Boolean.valueOf(flag).booleanValue();
   }

   
Perform the authentication of the username and password.
   @SuppressWarnings("unchecked")
   public boolean login() throws LoginException
   {
      // See if shared credentials exist
      ifsuper.login() == true )
      {
         // Setup our view of the user
         Object username = .get("javax.security.auth.login.name");
         ifusername instanceof Principal )
             = (Principalusername;
         else
         {
            String name = username.toString();
            try
            {
                = createIdentity(name);
            }
            catch(Exception e)
            {
               .debug("Failed to create principal"e);
               throw new LoginException("Failed to create principal: "e.getMessage());
            }
         }
         Object password = .get("javax.security.auth.login.password");
         ifpassword instanceof char[] )
             = (char[]) password;
         else ifpassword != null )
         {
            String tmp = password.toString();
             = tmp.toCharArray();
         }
         return true;
      }
      super. = false;
      String[] info = getUsernameAndPassword();
      String username = info[0];
      String password = info[1];
      ifusername == null && password == null )
      {
          = ;
         super..trace("Authenticating as unauthenticatedIdentity="+);
      }
      if == null )
      {
         try
         {
             = createIdentity(username);
         }
         catch(Exception e)
         {
            .debug("Failed to create principal"e);
            throw new LoginException("Failed to create principal: "e.getMessage());
         }
         // Hash the user entered password if password hashing is in use
         if != null &&  == true )
            password = createPasswordHash(usernamepassword"digestCallback");
         // Validate the password supplied by the subclass
         String expectedPassword = getUsersPassword();
         // Allow the storeDigestCallback to hash the expected password
         if != null &&  == true )
            expectedPassword = createPasswordHash(usernameexpectedPassword"storeDigestCallback");
         ifvalidatePassword(passwordexpectedPassword) == false )
         {
            Throwable ex = getValidateError();
            FailedLoginException fle = new FailedLoginException("Password Incorrect/Password Required");
            ifex != null )
            {
               .debug("Bad password for username="+usernameex);
               fle.initCause(ex);
            }
            else
            {
               .debug("Bad password for username="+username);
            }
            throw fle;
         }
      }
      ifgetUseFirstPass() == true )
      {    // Add the username and password to the shared state map
         .put("javax.security.auth.login.name"username);
         .put("javax.security.auth.login.password");
      }
      super. = true;
      super..trace("User '" +  + "' authenticated, loginOk="+);
      return true;
   }
   protected Principal getIdentity()
   {
      return ;
   }
   {
      return ;
   }
   protected Object getCredentials()
   {
      return ;
   }
   protected String getUsername()
   {
      String username = null;
      ifgetIdentity() != null )
         username = getIdentity().getName();
      return username;
   }

   
Called by login() to acquire the username and password strings for authentication. This method does no validation of either.

Returns:
String[], [0] = username, [1] = password
Throws:
javax.security.auth.login.LoginException thrown if CallbackHandler is not set or fails.
   protected String[] getUsernameAndPassword() throws LoginException
   {
      String[] info = {nullnull};
      // prompt for a username and password
      if == null )
      {
         throw new LoginException("Error: no CallbackHandler available " +
         "to collect authentication information");
      }
      
      NameCallback nc = new NameCallback("User name: ""guest");
      PasswordCallback pc = new PasswordCallback("Password: "false);
      Callback[] callbacks = {ncpc};
      String username = null;
      String password = null;
      try
      {
         .handle(callbacks);
         username = nc.getName();
         char[] tmpPassword = pc.getPassword();
         iftmpPassword != null )
         {
             = new char[tmpPassword.length];
            System.arraycopy(tmpPassword, 0, , 0, tmpPassword.length);
            pc.clearPassword();
            password = new String();
         }
      }
      catch(IOException e)
      {
         LoginException le = new LoginException("Failed to get username/password");
         le.initCause(e);
         throw le;
      }
      catch(UnsupportedCallbackException e)
      {
         LoginException le = new LoginException("CallbackHandler does not support: " + e.getCallback());
         le.initCause(e);
         throw le;
      }
      info[0] = username;
      info[1] = password;
      return info;
   }

  
If hashing is enabled, this method is called from login() prior to password validation.

Subclasses may override it to provide customized password hashing, for example by adding user-specific information or salting. If the legacyCreatePasswordHash option is set, this method tries to delegate to the legacy createPasswordHash(String, String) method via reflection and this is the value returned.

The default version calculates the hash based on the following options:

  • hashAlgorithm: The digest algorithm to use.
  • hashEncoding: The format used to store the hashes (base64 or hex)
  • hashCharset: The encoding used to convert the password to bytes for hashing.
  • digestCallback: The class name of the org.jboss.security.auth.spi.DigestCallback implementation that includes pre/post digest content like salts.
It will return null if the hash fails for any reason, which will in turn cause validatePassword() to fail.

Parameters:
username ignored in default version
password the password string to be hashed
digestOption - the login module option name of the DigestCallback
Throws:
java.lang.SecurityException - thrown if there is a failure to load the digestOption DigestCallback
   @SuppressWarnings("unchecked")
   protected String createPasswordHash(String usernameString password,
     String digestOption)
     throws LoginException
   {
      // Support for 4.0.2 createPasswordHash(String, String) override
      if )
      {
         try
         {
            // Try to invoke the subclass createPasswordHash(String, String)
            Class<?>[] sig = {String.classString.class};
            Method createPasswordHash = getClass().getMethod("createPasswordHash"sig);
            Object[] args = {usernamepassword};
            String passwordHash = (StringcreatePasswordHash.invoke(thisargs);
            return passwordHash;
         }
         catch (InvocationTargetException e)
         {
            LoginException le = new LoginException("Failed to delegate createPasswordHash");
            le.initCause(e.getTargetException());
            throw le;
         }
         catch(Exception e)
         {
            LoginException le = new LoginException("Failed to delegate createPasswordHash");
            le.initCause(e);
            throw le;            
         }
      }
      DigestCallback callback = null;
      String callbackClassName = (String.get(digestOption);
      ifcallbackClassName != null )
      {
         try
         {
            ClassLoader loader = SecurityActions.getContextClassLoader();
            Class<?> callbackClass = loader.loadClass(callbackClassName);
            callback = (DigestCallbackcallbackClass.newInstance();
            if.isTraceEnabled() )
               .trace("Created DigestCallback: "+callback);
         }
         catch (Exception e)
         {
            if.isTraceEnabled() )
               .trace("Failed to load DigestCallback"e);
            SecurityException ex = new SecurityException("Failed to load DigestCallback");
            ex.initCause(e);
            throw ex;
         }
         Map<String,Objecttmp = new HashMap<String,Object>();
         tmp.putAll();
         tmp.put("javax.security.auth.login.name"username);
         tmp.put("javax.security.auth.login.password"password);
         callback.init(tmp);
         // Check for a callbacks
         Callback[] callbacks = (Callback[]) tmp.get("callbacks");
         ifcallbacks != null )
         {
            try
            {
               .handle(callbacks);
            }
            catch(IOException e)
            {
               LoginException le = new LoginException(digestOption+" callback failed");
               le.initCause(e);
               throw le;
            }
            catch(UnsupportedCallbackException e)
            {
               LoginException le = new LoginException(digestOption+" callback failed");
               le.initCause(e);
               throw le;
            }
         }
      }
      String passwordHash = Util.createPasswordHash(,
         usernamepasswordcallback);
      return passwordHash;
   }

   
Get the error associated with the validatePassword failure

Returns:
the Throwable seen during validatePassword, null if no error occurred.
   protected Throwable getValidateError()
   {
      return ;
   }

   
Set the error associated with the validatePassword failure

Parameters:
validateError
   protected void setValidateError(Throwable validateError)
   {
      this. = validateError;
   }

   
A hook that allows subclasses to change the validation of the input password against the expected password. This version checks that neither inputPassword or expectedPassword are null that that inputPassword.equals(expectedPassword) is true;

Returns:
true if the inputPassword is valid, false otherwise.
   protected boolean validatePassword(String inputPasswordString expectedPassword)
   {
      ifinputPassword == null || expectedPassword == null )
         return false;
      boolean valid = false;
      if == true )
         valid = inputPassword.equalsIgnoreCase(expectedPassword);
      else
         valid = inputPassword.equals(expectedPassword);
      return valid;
   }


   
Get the expected password for the current username available via the getUsername() method. This is called from within the login() method after the CallbackHandler has returned the username and candidate password.

Returns:
the valid password String
   abstract protected String getUsersPassword() throws LoginException;
   
New to GrepCode? Check out our FAQ X