Wednesday, June 06, 2012

Ensure Password Rules for JPasswordField input

Java's standard regular expression classes like Pattern and Matcher only support CharSequence which includes String and StringBuffer but not char[]. And, for security reasons, it is important to never convert a password into a String. It is advisable to keep the password in a char array. So, how do you enforce password rules on a char array. The below code is a sample of how you will need to implement password rules:
      public static boolean isPasswordPatternValid(char[] password) {  
           if (password == null || password.length < 8) {  
                return false;  
           }  
           boolean hasDigit = false;  
           boolean hasLower = false;  
           boolean hasUpper = false;  
           boolean hasSpecial = false;  
           char[] specialChars = new char[] {'~','@','#','$','%','^','&','*','(',')'};  
           for (int i = 0; i < password.length; i++) {  
                if (!hasDigit && Character.isDigit(password[i])) {  
                     hasDigit = true;  
                     continue;  
                }  
                if (!hasLower && Character.isLowerCase(password[i])) {  
                     hasLower = true;  
                     continue;  
                }  
                if (!hasUpper && Character.isUpperCase(password[i])) {  
                     hasUpper = true;  
                     continue;  
                }  
                if (!hasSpecial) {  
                     for (int j = 0; j < specialChars.length; j++) {  
                          if (password[i] == specialChars[j]) {  
                               hasSpecial = true;  
                               break;  
                          }  
                     }  
                }  
           }  
           return true;  
      }  

Tuesday, June 05, 2012

JDialog with Multiple Input Fields

The below code displays password fields in a dialog window. The window is disposed when any of the buttons are clicked. If you want to prevent the dialog from closing if the entries are invalid, you will need to create custom dialog windows. An example of custom dialog is given below:
     

           //STANDARD JDialog code      
           final JPasswordField oldPassword = new JPasswordField();  
           final JPasswordField newPassword = new JPasswordField();  
           final JPasswordField confirmNewPassword = new JPasswordField();  
           final JComponent[] inputs = new JComponent[] {  
                     new JLabel("Old Password:"),  
                     oldPassword,  
                     new JLabel("New Password:"),  
                     newPassword,  
                     new JLabel("Confirm New Password:"),  
                     confirmNewPassword  
           };  
           int result = JOptionPane.showConfirmDialog(null, inputs, "Change Password", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);  
           System.out.println("Old Password:" + new String(oldPassword.getPassword()));  
           System.out.println("New Password:" + new String(newPassword.getPassword()));  
           System.out.println("Confirm New Password:" + new String(confirmNewPassword.getPassword()));  
           if(result == JOptionPane.OK_OPTION){  
                if (!KeyManager.isPasswordPatternValid(oldPassword.getPassword())
                      || !KeyManager.isPasswordPatternValid(newPassword.getPassword())) {  
                     JOptionPane.showMessageDialog (null, KeyManager.passwordPatternRules, "Invalid Password", JOptionPane.ERROR_MESSAGE);  
                     return;  
                }  
                if (!KeyManager.isPasswordReentryMatch(newPassword.getPassword(), confirmNewPassword.getPassword())) {  
                     JOptionPane.showMessageDialog (null, "Passwords do not match!", "Password Mismatch", JOptionPane.ERROR_MESSAGE);  
                     return;  
                }  
                KeyManager.changePassword(oldPassword.getPassword(), newPassword.getPassword());  
                return;  
           } else {  
                return;  
           }  

The following code is custom code that prevents the password entry dialog window from being closed if there are are errors.
          
 
                //CUSTOM JDialog code
  final JPasswordField oldPassword = new JPasswordField();
  final JPasswordField newPassword = new JPasswordField();
  final JPasswordField confirmNewPassword = new JPasswordField();
  final JComponent[] inputs = new JComponent[] {
    new JLabel("Old Password:"),
    oldPassword,
    new JLabel("New Password:"),
    newPassword,
    new JLabel("Confirm New Password:"),
    confirmNewPassword
  };
  final JOptionPane jop = new JOptionPane(inputs,
    JOptionPane.WARNING_MESSAGE,
    JOptionPane.OK_CANCEL_OPTION);
  final JDialog dialog = new JDialog(parentFrame, "Re-Enter Password:");
  dialog.setContentPane(jop);
  dialog.setVisible(true);
  jop.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent e) {
             String prop = e.getPropertyName();
             Object value = jop.getValue();
             if (value == JOptionPane.UNINITIALIZED_VALUE) {
                 return;
             }        
             jop.setValue(JOptionPane.UNINITIALIZED_VALUE);
          if (((Integer)value).intValue() == JOptionPane.CANCEL_OPTION ) {
        dialog.setVisible(false);
        return;
          }
             if (dialog.isVisible() 
              && (e.getSource() == jop)
              && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
              if (!KeyManager.isPasswordPatternValid(oldPassword.getPassword()) 
                || !KeyManager.isPasswordPatternValid(newPassword.getPassword())) {
         JOptionPane.showMessageDialog (null, KeyManager.passwordPatternRules, "Invalid Password", JOptionPane.ERROR_MESSAGE);
         return;
        }
        if (!KeyManager.isPasswordReentryMatch(newPassword.getPassword(), confirmNewPassword.getPassword())) {
         JOptionPane.showMessageDialog (null, "Passwords do not match!", "Password Mismatch", JOptionPane.ERROR_MESSAGE);
         return;
        }
        KeyManager.changePassword(oldPassword.getPassword(), newPassword.getPassword());
        dialog.setVisible(false);
        return;
             }
         }
     });