Home > Software engineering >  trying to make a login code that searches an array list for matching username and password
trying to make a login code that searches an array list for matching username and password

Time:04-02

I am trying to make a login code using javaFX that searches an arraylist for the username and password the user input. my code looks like this

for (int i=0; i< Admin.customers.size(); i  ){
        if(username.getText().equals(Admin.customers.get(i).getUsername()) && password.getText().equals(Admin.customers.get(i).getPassword())){
            wrongLogin.setText("it works lol");
        }
    }
    if(username.getText().equals("admin") && password.getText().equals("admin")){
        m.changeScene("ownerstartscreen.fxml");
    }         
    if(username.getText().isEmpty()&& password.getText().isEmpty()){
        wrongLogin.setText("Please enter your data");
    }
    else{
        wrongLogin.setText("Wrong username or password");
    } 

i tried switching up the order but it always seems to skip the searching part. when i type in admin for both fields it works but when i try inputting a username i hard coded into the array it doesnt work and always skips the for loop part. I tried removing the line in the equals method and hard code it to the same username and password as the one in the arraylist and still have the same issue

CodePudding user response:

This probably runs

wrongLogin.setText("it works lol");

But since you do not exit the for loop, microseconds later, wrongLogin is changed to "Wrong username or password"

CodePudding user response:

As mentioned by Tony you need to break the loop when a correct password is found, you can do something like this

for (int i=0; i< Admin.customers.size(); i  ){
    if(username.getText().equals(Admin.customers.get(i).getUsername()) && password.getText().equals(Admin.customers.get(i).getPassword())){
        wrongLogin.setText("it works lol");
        break;
    }
}
if(username.getText().equals("admin") && password.getText().equals("admin")){
    m.changeScene("ownerstartscreen.fxml");
        break;
}         
if(username.getText().isEmpty()&& password.getText().isEmpty()){
    wrongLogin.setText("Please enter your data");
        break;
}
else{
    wrongLogin.setText("Wrong username or password");
} 

CodePudding user response:

For a cleaner code, consider these two implementations:

Simple but unclean imlpementation:

package stackoverflow;

import java.util.ArrayList;
import java.util.Objects;

import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class CustomerLoginTest1 {

    static class Admin {
        public static ArrayList<Customer> customers;

        public static Customer getCustomerByName(final String pCustomerName) {
            if (pCustomerName == null) return null;

            for (final Customer customer : customers) {
                if (Objects.equals(pCustomerName, customer.getUsername())) return customer;
            }
            return null;
        }
    }
    static class Customer {
        private final String    mUserName;
        private final String    mPassword;
        public Customer(final String pUserName, final String pPassword) {
            mUserName = pUserName;
            mPassword = pPassword;
        }
        public String getUsername() {
            return mUserName;
        }
        public boolean matchesPassword(final String pTestPassword) {
            return Objects.equals(mPassword, pTestPassword);
        }
    }
    static class MyWindow { // dummy class
        public void changeScene(final String pString) {}
    }

    public static void main(final String[] args) {
        final MyWindow m = new MyWindow();

        // interactive method
        final boolean ok = checkForLogin(username.getText(), password.getText()); // getText creates a warning, because passwords should not be Strings but be handled as char[] or byte[] data
        if (ok) {
            m.changeScene("ownerstartscreen.fxml");
        }
    }


    static final JTextField     username    = new JTextField();
    static final JPasswordField password    = new JPasswordField();
    static final JTextField     wrongLogin  = new JTextField();


    private static boolean checkForLogin(final String pUserName, final String pPassword) {
        if (pUserName == null || pUserName.trim().length() < 1) {
            wrongLogin.setText("Please enter a valid username.");
            return false;
        }
        if (pPassword == null || pPassword.trim().length() < 1) {
            wrongLogin.setText("Please enter a valid password.");
            return false;
        }

        final Customer foundCustomer = Admin.getCustomerByName(pUserName);
        if (foundCustomer == null) {
            wrongLogin.setText("Wrong username. User not found by name ["   pUserName   "]");
            return false;
        }

        final boolean passwordMatches = foundCustomer.matchesPassword(pPassword);
        if (!passwordMatches) {
            wrongLogin.setText("Wrong password for user ["   foundCustomer   "]");
            return false;
        }

        wrongLogin.setText("It works. LoL!");
        return true;
    }



}

A better implementation. Here the login check does not know anything about the UI elements, and thus could be used everywhere.

package stackoverflow;

import java.util.ArrayList;
import java.util.Objects;

import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class CustomerLoginTest2 {

    static class Admin {
        public static ArrayList<Customer> customers;

        public static Customer getCustomerByName(final String pCustomerName) {
            if (pCustomerName == null) return null;

            for (final Customer customer : customers) {
                if (Objects.equals(pCustomerName, customer.getUsername())) return customer;
            }
            return null;
        }
    }
    static class Customer {
        private final String    mUserName;
        private final String    mPassword;
        public Customer(final String pUserName, final String pPassword) {
            mUserName = pUserName;
            mPassword = pPassword;
        }
        public String getUsername() {
            return mUserName;
        }
        public boolean matchesPassword(final String pTestPassword) {
            return Objects.equals(mPassword, pTestPassword);
        }
    }
    static class MyWindow { // dummy class
        public void changeScene(final String pString) {}
    }

    // have these exception classes each in their own file, withuot the static keyword
    static public class UserInputException extends IllegalArgumentException {
        private static final long serialVersionUID = 6758558948021224010L;
        public UserInputException(final String pReason, final Throwable pCause) {
            super(pReason, pCause);
        }
    }
    static public class BadUsernameException extends UserInputException {
        private static final long serialVersionUID = -714058768224400595L;
        public BadUsernameException(final String pReason, final Throwable pCause) {
            super(pReason, pCause);
        }
    }
    static public class BadPasswordException extends UserInputException {
        private static final long serialVersionUID = -9074024536171650229L;
        public BadPasswordException(final String pReason, final Throwable pCause) {
            super(pReason, pCause);
        }
    }



    public static void main(final String[] args) {
        final MyWindow m = new MyWindow();

        // exception-handling independent method
        try {
            final Customer authenticatedCustomer = checkForLogin(username.getText(), password.getText()); // getText creates a warning, because passwords should not be Strings but be handled as char[] or byte[] data
            wrongLogin.setText("It works. LoL!");
            m.changeScene("ownerstartscreen.fxml");
            // do sth with the authenticatedCustomer here...

        } catch (final UserInputException e) {
            wrongLogin.setText(e.getLocalizedMessage());
        } catch (final Exception e) {
            wrongLogin.setText("Unknown exception: "   e.getLocalizedMessage());
        }
    }



    static final JTextField     username    = new JTextField();
    static final JPasswordField password    = new JPasswordField();
    static final JTextField     wrongLogin  = new JTextField();


    private static Customer checkForLogin(final String pUserName, final String pPassword) {
        if (pUserName == null || pUserName.trim().length() < 1) throw new BadUsernameException("Please enter a valid username.", null);
        if (pPassword == null || pPassword.trim().length() < 1) throw new BadPasswordException("Please enter a valid password.", null);

        final Customer foundCustomer = Admin.getCustomerByName(pUserName);
        if (foundCustomer == null) throw new BadUsernameException("Wrong username. User not found by name ["   pUserName   "]", null);

        final boolean passwordMatches = foundCustomer.matchesPassword(pPassword);
        if (!passwordMatches) throw new BadPasswordException("Wrong password for user ["   foundCustomer   "]", null);

        return foundCustomer;
    }



}

For the shortness and compactness of code I have included all classes as static classes. If you wanna implement one of these methods, I suggest putting each of those in their own file.

Passwords

Oh and one little addition to the Customer.matchesPassword() method: usually, you do NOT want any password stored in plaintext. All passwords should be hashed (like SHA-512 etc) with some salt unique to your app. Then the hashes get compared. This is why I put the method into the Customer class. This way, not even the hash is shown publicly, and Customer takes care of checking the password.

  • Related