April 27th, 2009 by Lincoln Baxter III

Revisited – Acegi/Spring Security & JSF Login Page

A correction has been made to the post: http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/, fixing an issue where FacesMessages were not being displayed on failed authentications. Because the example had initially used the @PostConstruct annotation to trigger a method to handle the error message, the handleError() method was being called before the actual authentication event had taken place, thus, the handleError() method was triggering before any BadCredentialsExceptions were stored in the Session. Instead of creating an error handling method in the LoginBean itself, instead attach a PhaseListener which will intercept failed logins, and add the new FacesMessage before the RENDER_RESPONSE phase.

LoginErrorPhaseListener

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
 
import org.springframework.security.BadCredentialsException;
import org.springframework.security.ui.AbstractProcessingFilter;
 
impot util.FacesUtils;
 
public class LoginErrorPhaseListener implements PhaseListener
{
    private static final long serialVersionUID = -1216620620302322995L;
 
    @Override
    public void beforePhase(final PhaseEvent arg0)
    {
        Exception e = (Exception) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(
                AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
 
        if (e instanceof BadCredentialsException)
        {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
                    AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, null);
            FacesUtils.addErrorMessage("Username or password not valid.");
        }
    }
 
    @Override
    public void afterPhase(final PhaseEvent arg0)
    {}
 
    @Override
    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }
 
}

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
	<lifecycle>
		<phase-listener>login.LoginErrorPhaseListener</phase-listener>
	</lifecycle>
</faces-config>

Happy developing!

Posted in JSF, Spring

Leave a Comment




Please note: In order to submit code or special characters, wrap it in

[code lang="xml"][/code]
(for your language) - or your tags will be eaten.

Please note: Comment moderation is enabled and may delay your comment from appearing. There is no need to resubmit your comment.