views:

972

answers:

1

I have request scope backing bean for login page( I am using Spring Security ). When authentication error occurs Spring put it to context and I am trying add error message to my page.

public void doLogin() throws IOException {
    final FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext externalContext = context.getExternalContext();
    externalContext.dispatch("/j_spring_security_check");

    if (externalContext.getRemoteUser() == null) {
        Exception loginError = (Exception) externalContext.getSessionMap().get(
                AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
        if (loginError instanceof BadCredentialsException) {
            externalContext.getSessionMap().put(
                    AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, null);
            context.addMessage("loginBtn", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid credentials!", null));
            context.responseComplete();
        }
    }

    context.renderResponse();
}

my page:

  <a4j:form prependId="false">
        <h:panelGrid columns="2" cellpadding="5" >
            <h:outputText value="#{msgs.login_username}"/>
            <h:inputText id="j_username"/>

            <h:outputText value="#{msgs.login_password}"/>
            <h:inputSecret id="j_password"/>

            <h:outputText value=" "/>
            <f:facet name="footer">
                <h:panelGroup>
                    <h:commandButton type="submit" id="loginBtn" action="#{guest.doLogin}" value="#{msgs.login}" />
                    <rich:spacer width="5" height="1"/>
                    <rich:message id="errorForLogin" for="loginBtn">
                        <f:facet name="errorMarker">
                            <h:graphicImage value="./resources/forbidden.gif"/>
                        </f:facet>
                    </rich:message>
                </h:panelGroup>
            </f:facet>
        </h:panelGrid>
        <br/><br/>
    </a4j:form>

But it's don't works. I am trying put error displaying code to @PostConstruct method but this didn't help. This work only if I implement my PhaseListener but I think this is bad idea because it invokes on every request. What my mistake, there are some ways add error message from method, maybe in @PostConstruct method?

A: 

You can approach this from other side. As you use SpringSecurity, you can subclass AuthenticationProcessingFilter and override onUnsuccessfulAuthentication method. There you can put the code for desired behaviour. Then you just specify your custom authentication processing filter class instead of AuthenticationProcessingFilter in correspondent bean definition for Spring Security.

Maksym Govorischev