Revisited – Acegi/Spring Security & JSF Login Page
LincolnA 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!
![]() | About the author:Lincoln Baxter, III is a Senior Software Engineer at Red Hat, Inc., working on JBoss open-source projects. This blog represents his personal thoughts and perspectives, not necessarily those of his employer. He is a founder of OcpSoft, the author of PrettyFaces: bookmarking, SEO extensions for JSF, and an individual member of the JavaServerâ„¢ Faces Expert Group. When he is not swimming, running, or playing Ultimate Frisbee, Lincoln is focused on promoting open-source software and making web-applications more accessible for small businesses, individuals. His latest project is ScrumShark, an open-source, agile project management tool. |

