4

I'm currently designing a login system for a make-believe company, right now all I have is the Main login, which needs a lot of cleaning up. Below is my login handler.

private class LoginButtonHandler implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        if(_uid.getText().equalsIgnoreCase("Nathan") && _pwd.getText().equals("password")) {
            JOptionPane.showMessageDialog(null, "Congratulations on logging in!");
        } else {
          JOptionPane.showMessageDialog(null, "Error on login!");
        }
    }
}

As is, this works perfectly fine, but when I change it to

_pwd.getPassword.equals("password")

it directs straight to the else statement when everything is input correctly. What is wrong here? Full program below.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main extends JFrame {
    private static final int HEIGHT = 90;
    private static final int WIDTH = 400;

    JTextField _uid = new JTextField(10);
    JPasswordField _pwd = new JPasswordField(10);
    JButton _login = new JButton("Login");
    JButton _reset = new JButton("Reset");

    public Main() {
       super("Login - Durptech");
        Container pane = getContentPane();
        setLayout(new FlowLayout());

        add(new JLabel("User ID:"));
            add(_uid);
        add(new JLabel("Password:"));
            add(_pwd);

            add(_login);
                _login.addActionListener(new LoginButtonHandler());
            add(_reset);
                _reset.addActionListener(new ResetButtonHandler());

        /*if(_uid.getText().equals("") && _pwd.getText().equals("")) {
            _login.setEnabled(false);
        } else {
            _login.setEnabled(true);
        }*/

       setSize(WIDTH, HEIGHT);
       setResizable(false);
       setLocation(500, 300);
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       setVisible(true);
    }

    private class ResetButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            _uid.setText("");
            _pwd.setText("");
            _uid.requestFocusInWindow();
        }
    }

    private class LoginButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if(_uid.getText().equalsIgnoreCase("Nathan") && _pwd.getText().equals("password")) {
                JOptionPane.showMessageDialog(null, "Congratulations on logging in!");
            } else {
              JOptionPane.showMessageDialog(null, "Error on login!");
            }
        }
    }

    public static void main(String[] args) {
        new Main();
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Nathan Kreider
  • 516
  • 3
  • 7
  • 16
  • I don't know Java, but I think the lack of parentheses there may be relevant. – Ry- Mar 21 '12 at 03:07
  • here's a simple tutorial on how to make a login screen in swing: http://www.thepcwizard.in/2011/10/create-login-form-using-netbeans-ide.html – ThePCWizard Jan 11 '13 at 12:02

4 Answers4

13

You will want to get to know the API well, to make it your best friend. The key to solving this is to see what JPasswordField#getPassword() returns. Hint 1: it's not a String. Hint 2: you may want to solve this using the java.util.Arrays class methods.

The reason getPassword doesn't return a String is because of the way Java handles Strings -- it can store them in the String pool, allowing Strings to hang out in the program longer than you'd expect, and making the Strings potentially retrievable by malware -- something you don't want to have happen to a password. It's much safer to work with char arrays.

Incidentally, don't use JPasswords deprecated getText() method or change a char array to a String using the new String(char[]) constructor since as these both return a String, they are not secure.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
11

JPasswordField.getPassword() returns a char [] instead of a String. This is done for the sake of security. You should compare the characters inside the array instead of seeing if the char [] .equals(a String);

black panda
  • 2,842
  • 1
  • 20
  • 28
6

password.getPassword() returns a char[], and char[]'s aren't equal to Strings. So you need to compare it to a char[]:

if (Arrays.equals(password.getPassword(), new char[]{'p','a','s','s','w','o','r','d'}))
user207421
  • 305,947
  • 44
  • 307
  • 483
  • 2
    Are you sure about this? I don't think that equals will work for comparing one array to another since the array doesn't override the method, and you end up using the default equality method for the Object class which just does object equality (`==`). Instead use `java.util.Arrays#equals(...)` or `java.util.Arrays#deepEquals(...)` method. – Hovercraft Full Of Eels Mar 21 '12 at 03:11
  • 1
    @HovercraftFullOfEels Of course, stupid of me, thanks for the correction. See edit. – user207421 Mar 21 '12 at 05:14
  • 1
    And by using `"password".toCharArray()` you put the password in the string pool, whether or not you use the `getPassword` or `getText` method if I am not mistaken. – Robin Mar 21 '12 at 07:22
2

As all the other answers have said, JPasswordField returns a char[] when you call the getPassword() method. However, the way I have it set in my sample log on form is I have a method for validating the input. I have two arrays for storing usernames[] and passwords[] and then I have my username input, and my password input. The password input in my method changes the char[] to a string before continuing, you can do so like this:

 String PasswordTyped = new String(_pwd.getPassword());

Then take that string and place that in your 'if' statement:

 if (_uid.equals("Nathan") && PasswordTyped.equals("password") {
     JOptionPane.showMessageDialog(null, "Congrats, you logged in as Nathan");
 }

However, as I mentioned my validation method runs on the two arrays of usernames[] and passwords[], while accepting a string and a char[] as input. I will copy and paste my method so you can implicate it if you would like:

public static void validate(String u, Char[] pass) {
    String password = new String(pass);
    boolean uGood = false;
    String[] usernames = new String[2];
    String[] passwords = new String[usernames.length];

    usernames[0] = "Don";
    passwords[0] = "password";
    usernames[1] = "Jared";
    passwords[1] = "password";


    for (int i = 0; i < usernames.length; i++) {

        if (usernames[i].equals(u) && passwords[i].equals(password)) {
            uGood = true;
        }
    }
    if (uGood) {
        System.out.println("Hooray, you did it!");
    }
    else {
        JOptionPane.showMessageDialog(null, "Incorrect Username\nand/or Password.");
    }
}

Finally, you would call this validation method by typing:

validate(_uid.getText(), _pwd.getPassword());