简体   繁体   中英

Login form doesn't display validation message when password is wrong

I have a login mechanism consisting of a JSF page + managed bean + EJB, it works fine but the only bug is that i don't see the error message when the password is entered wrong. Any ideas?

When the password is entered wrong this is what i get in the browser:

在此处输入图片说明

I can avoid this if i don't throw a ValidationException at the catch in the EJB(See EJB code below) but then i don't see any validation message in the form at all when the password is entered wrong.

This is the code for the form at the page:

<h:form>
   <p:panel>                
                <h:outputText value="*Em@il:" />
                <h:inputText id="email" value="#{securityController.email}" binding="#{emailComponent}"/>                   
                <br/>
                <h:outputText value="*Lozinka: " />
                <h:inputSecret id="password" value="#{securityController.password}" validator="#{securityController.validate}">                     
                    <f:attribute name="emailComponent" value="#{emailComponent}" />
                </h:inputSecret>            

                <br/>
                <span style="color: red;"><h:message for="password"
                showDetail="true" /></span> 
                <br/>
                <h:commandButton value="Login" action="#{securityController.logIn()}"/>                 

            </p:panel>
        </h:form>

This is the code for the managedBean:

    @ManagedBean
@RequestScoped
public class SecurityController {

    @EJB
    private IAuthentificationEJB authentificationEJB;
    private String email;
    private String password;
    private String notificationValue;

    public String logIn() {
        if (authentificationEJB.saveUserState(email, password)) {
            notificationValue = "Dobro dosli";
            return "main.xhtml";
        } else {
            return "";
        }

    }   

    public void validate(FacesContext context, UIComponent component,
            Object value) throws ValidatorException {

        UIInput emailComponent = (UIInput) component.getAttributes().get(
                "emailComponent");
        String email = "";
        String password = "";
        email = (String) emailComponent.getValue();
        password = (String) value;

        String emailInput = email;
        String emailPatternText = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
        Pattern emailPattern = null;
        Matcher emailMatcher = null;
        emailPattern = Pattern.compile(emailPatternText);
        emailMatcher = emailPattern.matcher(emailInput);

        String passwordInput = password;
        String alphanumericPattern = "^[a-zA-Z0-9]+$";
        Pattern passwordPattern = null;
        Matcher passwordMatcher = null;
        passwordPattern = Pattern.compile(alphanumericPattern);
        passwordMatcher = passwordPattern.matcher(passwordInput);

        if (!emailMatcher.matches() && !passwordMatcher.matches()) {
            if (authentificationEJB.checkCredentials(emailInput, passwordInput) == false) {
                FacesMessage msg = new FacesMessage(
                        "Pogresan email ili lozinka");
                throw new ValidatorException(msg);
            }
        }
        if(emailInput == null || passwordInput == null) {
            FacesMessage msg = new FacesMessage("Pogresan email ili lozinka");
            throw new ValidatorException(msg);
        }
        if (passwordInput.length() <= 0 || emailInput.length() <= 0) {
            FacesMessage msg = new FacesMessage("Pogresan email ili lozinka");
            throw new ValidatorException(msg);
        }
    }

    public String getEmail() {
        return email;
    }

    public String getPassword() {
        return password;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getNotificationValue() {
        return notificationValue;
    }

    public void setNotificationValue(String notificationValue) {
        this.notificationValue = notificationValue;
    }
}

This is the code for the EJB

   @Stateful(name = "ejbs/AuthentificationEJB")
public class AuthentificationEJB implements IAuthentificationEJB {

    @PersistenceContext
    private EntityManager em;

    // Login
    public boolean saveUserState(String email, String password) {
        // 1-Send query to database to see if that user exist
        Query query = em
                .createQuery("SELECT r FROM Role r WHERE r.email=:emailparam AND r.password=:passwordparam");
        query.setParameter("emailparam", email);
        query.setParameter("passwordparam", password);
        // 2-If the query returns the user(Role) object, store it somewhere in
        // the session
        try {
            Role role = (Role) query.getSingleResult();
            if (role != null && role.getEmail().equals(email)
                    && role.getPassword().equals(password)) {
                FacesContext.getCurrentInstance().getExternalContext()
                        .getSessionMap().put("userRole", role);
                // 3-return true if the user state was saved
                System.out.println(role.getEmail() + role.getPassword());
                return true;
            }
        } catch (Exception e) {
                            FacesMessage msg = new FacesMessage("Pogresan email ili lozinka");
            throw new ValidatorException(msg); 
        }
        // 4-return false otherwise
        return false;
    }

    // Logout
    public void releaseUserState() {
        // 1-Check if there is something saved in the session(or wherever the
        // state is saved)
        if (!FacesContext.getCurrentInstance().getExternalContext()
                .getSessionMap().isEmpty()) {
            FacesContext.getCurrentInstance().release();
        }
        // 2-If 1 then flush it
    }

    // Check if user is logged in
    public boolean checkAuthentificationStatus() {
        // 1-Check if there is something saved in the session(This means the
        // user is logged in)
        if ((FacesContext.getCurrentInstance().getExternalContext()
                .getSessionMap().get("userRole") != null)) {
            // 2-If there is not a user already loged, then return false
            return true;
        }

        return false;
    }

    @Override
    public boolean checkCredentials(String email, String password) {
        Query checkEmailExists = em
                .createQuery("SELECT COUNT(r.email) FROM Role r WHERE r.email=:emailparam AND r.password=:passwordparam");
        checkEmailExists.setParameter("emailparam", email);
        checkEmailExists.setParameter("passwordparam", password);
        long matchCounter = 0;
        matchCounter = (Long) checkEmailExists.getSingleResult();
        if (matchCounter > 0) {
            return true;
        }
        return false;
    }
}

Here in the EJB i think i make a mistake if i throw the ValidationException in the catch block, because i think displaying error messages at the front end should be a task for the managed bean. I dont understand why the form does not display the error as it does when the fields are empty when the password is wrong(When the email is wrong it displays correctly the validation message).

Changed the saveUserState() method at the EJB to:

// Login
public boolean saveUserState(String email, String password) {
    // 1-Send query to database to see if that user exist
    Query query = em
            .createQuery("SELECT r FROM Role r WHERE r.email=:emailparam AND r.password=:passwordparam");
    query.setParameter("emailparam", email);
    query.setParameter("passwordparam", password);
    // 2-If the query returns the user(Role) object, store it somewhere in
    // the session
    List<Object> tmpList = query.getResultList();
    if (tmpList.isEmpty() == false) {
        Role role = (Role) tmpList.get(0);
        if (role != null && role.getEmail().equals(email)
                && role.getPassword().equals(password)) {
            FacesContext.getCurrentInstance().getExternalContext()
                    .getSessionMap().put("userRole", role);
            // 3-return true if the user state was saved
            System.out.println(role.getEmail() + role.getPassword());
            return true;
        }
    }
    // 4-return false otherwise
    return false;
}

The check credentials method:

public boolean checkCredentials(String email, String password) {
    Query checkEmailExists = em
            .createQuery("SELECT COUNT(r) FROM Role r WHERE r.email=:emailparam AND r.password=:passwordparam");
    checkEmailExists.setParameter("emailparam", email);
    checkEmailExists.setParameter("passwordparam", password);
    int matchCounter = 0;
    matchCounter = checkEmailExists.getResultList().size();
    if (matchCounter == 1) {
        return true;
    }
    return false;
}

You should not throw the JSF ValidatorException inside an EJB method, but inside a JSF validate() method.

I'm not sure what went wrong in the EJB which caused this exception, probably getSingleResult() didn't return a single result at all (thus zero or many). You need to change/handle this accordingly, either by using getResultList() or revising your datamodel why the user doesn't have a single role. I think you just need getResultList() because you're apparently allowing a null outcome.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM