0

Previously I created a login system which used a HashMap, but no database. I then ran into the problem of not being able to change the passwords of the system, as they would be reset everytime I booted up the program. It was like this:


HashMap<String, String> credentials = new HashMap<String, String>();

    UserData() {
        credentials.put("Manager", "adminpass");
        credentials.put("Employee", "employeepass");
        credentials.put("Customer", "customerpass");

    }

I then realised I want to use text files to store the passwords, so I could edit them and the changes would take effect. So I created 3 text files. adminpass.txt, employeepass.txt, customerpass.txt They all contain the passwords which are 'adminpass', 'employeepass', 'customerpass' With the previous system, I used .equals to compare the password of user input and the real password as it was a string. Now it's a variable, so I am using ==. Here is my code for logging in:

public void actionPerformed(ActionEvent ae) {

                if (ae.getSource() == authenticateButton) {

                    String roleID = usernameField.getText();
                    String password = String.valueOf(((JPasswordField) passwordField).getPassword());

                    if (credentials.containsKey(roleID)) {
                        if (credentials.get(roleID) == password) {
                            messageLabel.setForeground(Color.green);
                            messageLabel.setText("Login successful");
                            frame.dispose();
                            m.launch(roleID);

                        } else {
                            messageLabel.setForeground(Color.red);
                            messageLabel.setText("Incorrect password");
                            
                        }

                    } else {
                        messageLabel.setForeground(Color.red);
                        messageLabel.setText("Incorrect username");
                    }
                }
            }
        });

I also have read from the text files on startup, assigning what the system has read from the files to the adminpass, employeepass, and customerpass variables. Everytime I login I get 'incorrect password' even though they're correct. So I decided to do

System.out.println(credentials.get(roleID))

And it just returns null. I'm completely confused here, I am grateful if anyone can help or point me in the right direction! Thanks! EDIT: when i use .equals(password), i get Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "java.util.HashMap.get(Object)" is null

  • 2
    Does this answer your question? [How do I compare strings in Java?](https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) Actually, your reasoning to replace `equals` with `==` is a bit vague, and this replacement seems to be a root cause of failure. – Alex Rudenko Mar 20 '21 at 20:42
  • @AlexRudenko No. As I said previously, I had `equals`, but it returns this error: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "java.util.HashMap.get(Object)" is null – honka11111111111111 Mar 20 '21 at 21:07
  • 2
    You have a `HashMap credentials` inside `UserData` class. Is it the same `credentials` accessed in the `actionPerformed`? Did you try to print entire map `System.out.println(credentials);` within `actionPerformed`? You should provide more details as a minimum reproducible example. The posted code is not sufficient to diagnose the issue precisely. – Alex Rudenko Mar 20 '21 at 21:46

1 Answers1

0

This syntax makes no sense to me:

    UserData() {

You have not provided quite enough detail to pinpoint your problem. But this error message:

"java.util.HashMap.get(Object)" is null

… tells us you likely have a problem with populating your Map.

Map.of

I suggest starting with a simple hard-coded map, to test your code. Take baby steps, building up your app piece by piece.

package work.basil.example.authenticate;

import java.util.Map;

public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        Map < String, String > credentials =
                Map.of(
                        "Manager" , "adminpass" ,
                        "Employee" , "employeepass" ,
                        "Customer" , "customerpass"
                );
        boolean authenticatedManager = credentials.get( "Manager" ).equals( "adminpass" );
        boolean authenticatedEmployee = credentials.get( "Employee" ).equals( "employeepass" );
        boolean authenticatedCustomer = credentials.get( "Customer" ).equals( "customerpass" );

        System.out.println( "credentials = " + credentials );
        System.out.println( "authenticatedManager = " + authenticatedManager );
        System.out.println( "authenticatedEmployee = " + authenticatedEmployee );
        System.out.println( "authenticatedCustomer = " + authenticatedCustomer );
    }
}

When run.

credentials = {Employee=employeepass, Customer=customerpass, Manager=adminpass}
authenticatedManager = true
authenticatedEmployee = true
authenticatedCustomer = true

After getting that to work, then replace Map.of hard-coding with a Map populated from your text file or database.

By the way, I'll ignore the issue of saving passwords in plain text. That is obviously the wrong way to manage authentication. I assume you are just learning/practicing, not doing real work for production use.

Populating a map

Here is how to populate a map from this example text file:

Scott,tiger
Alice,password123
Bob,letmein

Example code using NIO.2. See tutorial by Oracle.

String pathText = "/Users/basilbourque/cred.txt";
Path path = Paths.get( pathText );
Map < String, String > tempCredentials = new HashMap <>();
try ( BufferedReader reader = Files.newBufferedReader( path , StandardCharsets.UTF_8 ) )
{
    String line = null;
    while ( ( line = reader.readLine() ) != null )
    {
        System.out.println( line );
        String[] parts = line.split( "," );
        String user = Objects.requireNonNull( parts[ 0 ] ).strip();
        String pw = Objects.requireNonNull( parts[ 1 ] ).strip();
        if ( user.isBlank() || pw.isBlank() ) { System.out.println( "Add code here to deal with invalid blank inputs. " ); }
        tempCredentials.put( user , pw );
    }
}
catch ( IOException x )
{
    System.err.format( "IOException: %s%n" , x );
}
Map < String, String > credentials = Map.copyOf( tempCredentials ); // Make an unmodifiable map, copied from temporary map.

System.out.println( "credentials = " + credentials );

When run.

Scott,tiger
Alice,password123
Bob,letmein
credentials = {Bob=letmein, Alice=password123, Scott=tiger}

Testing equality

You said:

so I am using ==.

Use == syntax only when asking if two references point to the very same object, the very same chunk of memory.

More commonly you want to compare the content of the objects to see if they are equivalent. For that, use the equals method or some similar method.

Basil Bourque
  • 218,480
  • 72
  • 657
  • 915