Package au.net.causal.projo.prefs.security

Source Code of au.net.causal.projo.prefs.security.ConsoleUiPasswordSource

package au.net.causal.projo.prefs.security;

import java.io.Console;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;

import au.net.causal.projo.prefs.PreferencesException;

/**
* Password source that reads passwords from the console.
* <p>
*
* By default, if a non-echoing method of reading passwords from the console is not available, this password source throws an exception when attempting
* to read a password.  However, if having passwords echoed on the screen is not a problem, the {@link #setEchoAllowed(boolean)} method can be used to control
* this behaviour.
*
* @author prunge
*/
public class ConsoleUiPasswordSource implements UiPromptPasswordSource
{
  private boolean echoAllowed;
  private String echoWarningText = "Warning: password will be echoed to the screen!";
  private String prompt = "Configuration master password";
  private String verifyPrompt = "Re-enter password";
  private String verifyErrorMessage = "Passwords were not the same.";

  public static void main(String... args)
  throws Exception
  {
    ConsoleUiPasswordSource s = new ConsoleUiPasswordSource();
    s.setEchoAllowed(true);
    char[] p = s.readPassword(Mode.ENCRYPTION);
    System.err.println("The password is: " + String.valueOf(p));
  }
 
  /**
   * Returns whether the password is allowed to be echoed on the screen.
   *
   * @return true if the password can be echoed to the console, false if not.
   *
   * @see #setEchoAllowed(boolean)
   * @see #setEchoWarningText(String)
   */
  public boolean isEchoAllowed()
  {
    return(echoAllowed);
  }

  /**
   * Sets whether the password entered by the user may be echoed to the console.
   * <p>
   *
   * This source will always try to get a non-echoing password when possible.  However, when this capability is not available, if this setting is enabled,
   * password may still be entered by the user, however it will be echoed to the screen.  If this setting is disabled, an error will occur in the
   * application instead.
   *
   * @param echoAllowed true to allow echo, false not to.
   *
   * @see #isEchoAllowed()
   * @see #setEchoWarningText(String)
   */
  public void setEchoAllowed(boolean echoAllowed)
  {
    this.echoAllowed = echoAllowed;
  }
 
  /**
   * If password echo is allowed, and when there is no capability to read passwords from the console without echoing, this warning text is displayed to
   * the user to inform them that others may be able to read the password from the screen.
   *
   * @return the echo warning text.
   *
   * @see #setEchoWarningText(String)
   */
  public String getEchoWarningText()
  {
    return(echoWarningText);
  }

  /**
   * Sets the warning text that is written to the console before the prompt when entering the password will cause it to echo on the screen.
   * <p>
   *
   * Only used when echo is allowed.
   *
   * @param echoWarningText the echo warning text.
   *
   * @see #getEchoWarningText()
   */
  public void setEchoWarningText(String echoWarningText)
  {
    this.echoWarningText = echoWarningText;
  }
 
  /**
   * Returns the message displayed when the password and the verify password are not the same.
   *
   * @return the verify error message.
   *
   * @see #setVerifyErrorMessage(String)
   */
  public String getVerifyErrorMessage()
  {
    return(verifyErrorMessage);
  }

  /**
   * Sets the message displayed when the password and the verify password are not the same.
   *
   * @param verifyErrorMessage the verify error message.
   *
   * @see #getVerifyErrorMessage()
   */
  public void setVerifyErrorMessage(String verifyErrorMessage)
  {
    this.verifyErrorMessage = verifyErrorMessage;
  }

  @Override
  public char[] readPassword(Mode mode) throws PreferencesException
  {
    char[] password;
   
    Console console = System.console();
    if (console == null)
    {
       if (isEchoAllowed())
       {
         //Since we are echoing the password anyway no need to make the user validate by typing second time
        
         if (!StringUtils.isEmpty(getEchoWarningText()))
           System.err.println(getEchoWarningText());
     
         if (!StringUtils.isEmpty(getPasswordPrompt()))
           System.err.print(getPasswordPrompt() + ": ");
        
         @SuppressWarnings("resource") //Don't want to close System.in
         Scanner sc = new Scanner(System.in);
         try
         {
           password = sc.nextLine().toCharArray();
         }
         catch (NoSuchElementException e)
         {
           //End of System.in stream possible I guess, regard as a cancel
           password = null;
         }
       }
       else
         throw new PreferencesException("Console not available, cannot read password from user securely.");
    }
    else
    {
      if (mode == Mode.ENCRYPTION)
      {
        boolean passwordsAreTheSame;
        do
        {
          if (!StringUtils.isEmpty(getPasswordPrompt()))
             System.err.print(getPasswordPrompt() + ": ");
         
          password = console.readPassword();
         
          //User cancelled
          if (password.length == 0)
            return(null);
         
          if (!StringUtils.isEmpty(getVerifyPrompt()))
            System.err.print(getVerifyPrompt() + ": ");
           
          char[] verifyPassword = console.readPassword();
         
          passwordsAreTheSame = Arrays.equals(password, verifyPassword);
          if (!passwordsAreTheSame && !StringUtils.isEmpty(getVerifyErrorMessage()))
            System.err.println(getVerifyErrorMessage());
        }
        while (!passwordsAreTheSame);
      }
      else
      {
        if (!StringUtils.isEmpty(getPasswordPrompt()))
           System.err.print(getPasswordPrompt() + ": ");
       
        password = console.readPassword();
      }
    }
     
    //If the user just presses ENTER regard as a cancel
    if (password != null && password.length == 0)
      password = null;
   
    return(password);
  }

  @Override
  public String getPasswordPrompt()
  {
    return(prompt);
  }

  @Override
  public void setPasswordPrompt(String prompt)
  {
    this.prompt = prompt;
  }

  public String getVerifyPrompt()
  {
    return(verifyPrompt);
  }

  public void setVerifyPrompt(String verifyPrompt)
  {
    this.verifyPrompt = verifyPrompt;
  }
}
TOP

Related Classes of au.net.causal.projo.prefs.security.ConsoleUiPasswordSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.