October 9th, 2008 by Lincoln Baxter III

Acegi/Spring Security Integration – JSF Login Page

Tutorials – What a nightmare

Everyone seems to be going through hell to get a fully functional JSF login page working with Spring Security (formerly Acegi,) and yes, I did too, but there’s an EASY way to make this happen. And get this:
  • It takes just five clear and well written lines of Java code.
First, the solution. Afterwards, the dirty details. (Spring 2.5.2 was used for this example, but this documentation is still relevant for Spring 3.x) You can find a downloadable working example here. There is also a followup article on post-authentication redirecting, here.

The Solution:

public class LoginBean
{
    //managed properties for the login page, username/password/etc...
 
    // This is the action method called when the user clicks the "login" button
    public String doLogin() throws IOException, ServletException
    {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
 
        RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())
                 .getRequestDispatcher("/j_spring_security_check");
 
        dispatcher.forward((ServletRequest) context.getRequest(),
                (ServletResponse) context.getResponse());
 
        FacesContext.getCurrentInstance().responseComplete();
        // It's OK to return null here because Faces is just going to exit.
        return null;
    }
}

—-

For anyone who was struggling because Spring Security requires you to use a Filter to intercept the login postback, thus either preventing you from being able to do JSF style validation, or visa-versa, creating a scenario where JSF can process results, but blocks Acegi from processing the request parameters. Simply use an HttpRequestDispatcher to allow both JSf and Spring Security to function one after another. JSF goes first, then delegates work to a Spring Security  (thus preserving any request parameters that Spring Security is looking for.) After forwarding, tell JSF you have finished, and not to do any more work, immediately stop processing. If the login credentials were bad, redirect to the Login page. If the credentials were good, redirect to the requested URL. You can even show a dynamic message for bad credentials. Add the following PhaseListener to your faces-config.xml in order to extract any login errors, and display a message to the user:
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;
 
import uk.co.pkit.project.view.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>

web.xml

You must configure your Spring Security Filter Chain to process Servlet FORWARD as well as REQUESTs.
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

—-

applicationContext-security.xml

As for the Spring Security configuration, everything can be left pretty standard. The relevant parts of my configuration, for example:
<?xml version="1.0" encoding="UTF-8"?>
 
<beans:beans
	xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                        http://www.springframework.org/schema/security
                         http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
 
	<global-method-security
		secured-annotations="enabled">
	</global-method-security>
 
	<http
		auto-config="true"
		access-denied-page="/accessDenied.jsp">
 
		<intercept-url
			pattern="/login*"
			access="IS_AUTHENTICATED_ANONYMOUSLY" />
		<intercept-url
			pattern="/**"
			access="ROLE_USER,ROLE_ADMIN" />
 
		<form-login
			login-processing-url="/j_spring_security_check"
			login-page="/login"
			default-target-url="/"
			authentication-failure-url="/login" />
		<logout logout-url="/logout"
			logout-success-url="/" />
	</http>
 
	<authentication-provider>
                <!-- Your authentication provider here (example below)-->
	</authentication-provider>
</beans:beans>

—-

Notice here that the “login-processing-url” is set to “/j_spring_security_check”, which is the location where our HttpRequestDispatcher is going to forward to. You can call this whatever you want, but the two must match exactly.

login.xhtml / login.jspx / login.jsp

(Whatever you use as your JSF page content type, take your pick.) So the last part of the puzzle is relatively easy. You need a JSF login page that conforms to Spring Security’s parameter naming requirements. When this page submits, its values will be forwarded to the Spring Security Filter Chain. Notice that you don’t even need to tie the input field values to a JSF backing bean! The values only need to be intercepted by Spring Security on forward. However, if you want to do all that cool validation and stuff that JSF lets you do… go for it. I just wanted to save space in the article, and prove a point that it’s not needed.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root
	xmlns:jsp="http://java.sun.com/JSP/Page"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	version="2.0">
 
	<f:view>
		<h:form
			id="loginForm"
			prependId="false">
			<label for="j_username"><h:outputText value="Username:" /><br />
			</label>
			<h:inputText
				id="j_username"
				required="true">
			</h:inputText>
 
			<br />
			<br />
			<label for="j_password"><h:outputText value="Password:" /><br />
			</label>
			<h:inputSecret
				id="j_password"
				required="true">
			</h:inputSecret>
 
			<br />
			<br />
			<label for="_spring_security_remember_me"> <h:outputText
				value="Remember me" /> </label>
			<h:selectBooleanCheckbox
				id="_spring_security_remember_me" />
			<br />
 
			<h:commandButton
				type="submit"
				id="login"
				action="#{loginBean.doLogin}"
				value="Login" />
 
		</h:form>
	</f:view>
</jsp:root>
Remember that Spring Security is expecting parameters to be named as they are in this file. j_username, j_password, _spring_security_remember_me. Don’t change these ids unless you change your Spring configuration.

—-

If you’re having problems

Add a LoggerListener to allow Spring Security to print messages to your logging output. This will allow you to view any error messages that may be occurring. (Note: This should be copied verbatim)
	<bean id="loggerListener"
		class="org.springframework.security.event.authentication.LoggerListener" />

—-

Finished

And that’s all it took. A simple forward to a new servlet. No JSF navigation cases, no extra configuration. Just a little J2EE, and a night of no sleep. I hope this helps a LOT of people who seem to be struggling with the task of integrating these two excellent frameworks. Considering the forces of this problem, we really required almost no invasiveness in our normal application logic. JSF does its validation and processing without being impacted by Acegi, and Acegi can perform its magic authentication without knowing that JSF was ever the provider of its parameters. You can see a working example of this guide here. Enjoy.

Example Authentication Provider for Testing

	<!--
		Usernames/Passwords are rod/koala dianne/emu scott/wombat peter/opal
	-->
	<authentication-provider>
		<password-encoder
			hash="md5" />
		<user-service>
			<user
				name="rod"
				password="a564de63c2d0da68cf47586ee05984d7"
				authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
			<user
				name="dianne"
				password="65d15fe9156f9c4bbffd98085992a44e"
				authorities="ROLE_USER,ROLE_TELLER" />
			<user
				name="scott"
				password="2b58af6dddbd072ed27ffc86725d7d3a"
				authorities="ROLE_USER" />
			<user
				name="peter"
				password="22b5c9accc6e1ba628cedc63a72d57f8"
				authorities="ROLE_USER" />
		</user-service>
	</authentication-provider>

Need more info?

Try one of these highly-recommended books, written by Spring Developers and Spring Experts:
Need more info?

Try one of these highly-recommended books:

Lincoln Baxter, III

About the author:

Lincoln Baxter, III is a Principal Software Engineer at Red Hat, working on JBoss open-source projects; most notably as creator & project lead of JBoss Forge, and author of Errai UI. This blog represents his personal thoughts and perspectives, not necessarily those of his employer.

He is a founder of OCPsoft, the author of PrettyFaces and Rewrite, the leading URL-rewriting extensions for Servlet, Java EE, and Java web frameworks; he is also the author of PrettyTime, social-style date and timestamp formatting for Java. 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.

Posted in Java, JSF

64 Comments

  1. BalusC says:

    Nice one.

    Though, the five lines of Java code can be reduced to three or four lines if you used ExternalContext#dispatch() ;)

  2. damnifiknow says:

    Presently I’m using a custom security realm within Glassfish for authentication. Being very green behind the ears to JSF and Spring how would that fit into the authentication-provider model? Would it be possible to see a full example of your solution? Way cool stuff!

  3. Matt says:

    Best post on this topic I’ve seen! Any way of getting a little more of your sample code? I’m working on catching the BadCredentialsException and displaying per instructions above but don’t think I have things set up quite right.

  4. Lincoln says:

    What else would you like to see in particular? Send me an email with your scenario.

    The BadCredentialsException is actually not caught, but is saved in the HttpSession object by Spring Security (which is why you get it out with a key.) So whenever your Login page is about to render, you need to check for that stored Exception object and handle your processing before the render response phase.

    I did this using a “request” scoped LoginBean, so that a new bean is created every request. Since JSF is invoked after Spring Security processes any submissions, the Exception object will already be populated by the time the LoginBean is being constructed by JSF.

    This being known, you can use the @PostConstruct annotation (see my example above) in order to do the Exception processing, and add a FacesMessage to the queue.

    These FacesMessage objects will not be displayed unless you place a <h:messages globalOnly=”true”/> tag somewhere on your page.

    Does this help?

  5. Lincoln says:

    I’ve posted an example AuthenticationProvider that I got from another tutorial site. (See above)

  6. Dave says:

    Hello,

    if I have clicked to button on login page nothing happend. I wasnt redirect nowhere? Can you publish all source code for this example please?

  7. Dave says:

    Moreover I can´t debug method doLogin in LoginBean cause application skip this part. :-(

  8. Lincoln says:

    I can’t publish the full source, but it sounds like your JSF LoginBean action method is either not being called, or not doing the forward. But if it is, make sure that you have properly configured your Spring Security to intercept the “login-processing-url” which is being forwarded to.

    Let me know if this helped solve your problem, or if you could post more details that would be great.

    This post is a good basic spring-security intro:
    http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/

  9. Lincoln says:

    If your doLogin() method is not being called. Make sure that you have properly configured your LoginBean with faces-config.xml, and also make sure that your EL expression in your JSP matches the name of the method, eg: action=”#{loginBean.doLogin}”

  10. Dave says:

    So, LoginBean seems to be working for now. But there is other issue. From login page I am everytime redirect to failure-url.

    My applicationContext-security.xml configuration:

    login-processing-url=”/faces/j_spring_security_check”
    login-page=”/faces/login.jspx”
    authentication-failure-url=”/faces/error.jsp”
    pattern=”/faces/jsp/**” access=”ROLE_USER,ROLE_ADMIN”

  11. Lincoln says:

    This probably means that your authentication is failing. See above for how to add a LoggerListener to see what Spring Security is doing/complaining about. You’ll need to have a logger set up. (It’s added right above the “Finished” section.)

  12. Dave says:

    I know, where is problem, but I don´t know why.:-)

    I have h:inputText id=”j_username” and h:inputText id=”j_password”. But it seems that values from these fields are not propagated to processing.

    Exception: WARNING: Authentication event AuthenticationFailureBadCredentialsEvent: ; details: org.springframework.security.ui.WebAuthenticationDetails@0: RemoteIpAddress: 10.0.0.2; SessionId: 2e1062b9cf6cdd18dcbec0710981641ee69527df73809aad3aa757501920f86f; exception: Bad credentials

    As you can see, credentials fields are empty.

  13. Lincoln says:

    That exception is also thrown if the username/password are incorrect.

  14. Dave says:

    Username/Password is correct

  15. Dave says:

    I am now sure, that values of j_username and j_password are empty.

    I have implemented UserDetailsService and value of login for method public UserDetails loadUserByUsername(String login) is everytime empty.

    Do you have any idea why values are not initialized?

  16. Lincoln says:

    We’re working on creating a project file that will demonstrate a full working example. It should be coming in a few days.

  17. Stace Merkel says:

    I’m new to this…

    I’m using Spring / Spring Security / Orchestra / Eclipselink. While I have the general spring security login page working I have tried your example but when I run the app I get java.lang.RuntimeException: Cannot find FacesContext.

    I tried using the loggerListener but nothing is printed out.

    What am I doing wrong?

  18. Stace Merkel says:

    Ok I tried something else…

    In my web.xml the faces servlet is mapped to /faces/* so I modified my springContext login-page entry under form-login to be “/faces/Login.jspx”.

    Using IE7 when I run the app it appears that an attempt to redirect gets stuck in a loop … in the bottom left hand corner of IE7 “Redirecting to site: … Login.jspx” flashes rapidly but the Login.jspx page is never displayed.

  19. jan says:

    I got the example working and if I try to access a secured page via the browser address text field it opens the login page. But when I try to enter the secured page via the faces-config.xml navigation rules, it doesn’t matter if I am logged in or not, I always have access. Is this the intended behavior? Are navigation rules outside the control of Spring Security?

  20. Derek says:

    Yes, unless you do a redirect in your navigation case. Spring security is based around Servlet Filters, so JSF navigation, without redirect, doesn’t leave the servlet until after the page is rendered. You should be able to fix this by adding the redirect property to the navigation cases in your faces-config.xml file.

  21. jan says:

    Thanks Derek. I am new to JSF so I hope you do not mind me asking if doing redirects all the time for security reasons is advisable (e.g. what about performance?)?

  22. [...] gotten a good number of comments from Lincoln’s latest post on Spring Security and JSF.  A few comments have asked for further code samples on how to get this example working.  We [...]

  23. Lincoln says:

    Derek finished his working example. You can download the source and run it here:

    http://ocpsoft.com/java/acegi-spring-security-jsf-integration-project-continued/

  24. Stace says:

    I am now able to display the login page but when I click the login during a debug session and step into the doLogin method when I reach the dispatcher.forward… statement I get javax.faces.el.EvaluatorException: java.lang.NullPointerException. I have checked my code against Derek’s example… any ideas what could be causing this?

  25. Josh says:

    Credentials fields j_username and j_passwords are not being passed to the backend for proecessing just like Dave says above.

    Does anyone have a solution to this problem?

    I am using NetBeans 6.1 and Tomcat 6.0.14

    Thanks

    Josh.

  26. wumbrath says:

    Josh and Dave…

    I had the same problem using MyFaces 1.2.2. The problem was that due to a bug the j_username and j_pasword fields were prepended by “null:” although the prependId=false.

    I upgraded to MyFaces 1.2.4 and all is fine now.

  27. Stace says:

    Has anyone tried the MyFaces Tomahawk library inputText tag’s “forceId” property which is supposed to ensure expected IDs are in the Acegi filter? I want to try this later today…

  28. Nguyen says:

    Hi,
    how can i get and show stored Username (when user chose “remember me” option). Im new in Acegi
    thanks in advance

  29. Nguyen says:

    hi,
    when i chose “remember me”, and then i click on log out, i can although access secret page (without username and password)
    when can i really log out?
    thanks

  30. Tyler says:

    Has anyone gotten this example to work as one would expect, specifically the ‘protected’ page being intercepted properly?

  31. Stace says:

    No. Haven’t got it working yet. I also posted at Spring Community Forums hoping for additional help.

  32. Shane says:

    I haven’t figured this out yet either. I can get things to successfully authenticate (against a test user-service), but the forward call is not working. If I return null from doLogin, I remain at the login page. If I return my normal ‘success’ String and let jsf handle navigation via a redirect, I get an IllegalStateException. If I remove the redirect, no navigation. What jsf impl/version are people using? I’m trying MyFaces 1.1 / Trinidad.

  33. Yennick Trevels says:

    Shane, try to set the once-per-request parameter to false in the http tag, like this:

    This fixed the forwarding problem for me.

  34. Allen says:

    Hi Lincoln,

    I just tried your example and most part of it worked very well, except the bad credential part. When I input the wrong password, the web page still stay in login page but with no error message. Any idea how to solve this problem?

  35. Lincoln says:

    That’s interesting. You just tried the basic example that we put up for download? What are you running on?

  36. Allen says:

    I tried your example with Jetty 6.1.14, jdk 1.6.0_11.

  37. dibya says:

    I downloaded the latest code from your site . When i run it i see the home page.
    When i click on the Secret link then it says
    “The requested resource (/faces/protected.jsf) is not available. ”
    I am deploying on Tomcat 6 .
    What can be the problem here.

    The content of security config file is as below ::

  38. Lincoln says:

    I’m not sure. I suggest posting on the forums at springframework.org.

  39. LukAnt says:

    You might have wrong address in “a herf” tag placed on home.jsp page. It depends on the address where the app is deployed. And it is case sensitive.

  40. Joachim says:

    Great work, THX!!!

    Just a few words for those of you who have to use JSF 1.1 (e.g. Tomcat 5.5):

    Because JSF 1.1. does not know the ‘prependId’ in the form-tag you run into a problem with the resolution of the form-names j_username and j_password. Internal they will be sth. like ‘loginForm:j_username’ or ‘_id0:j_username’.

    To solve that I changed the doLogin()-method; remove the second line with the following:

    Map map = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
    String j_user = map.get(“loginForm:j_username”);
    String j_pwd = map.get(“loginForm:j_password”);
    RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher(“/j_spring_security_check?j_username=”+j_user+”&j_password=”+j_pwd);

    This can be a security-risk due to passing the password via GET parameter, so use at your own risk ;)

  41. Danny Fürniß says:

    Great post, Lincoln! I set up my app this way and got it working as desired in a few minutes. The only issue i am facing problems with is the bad credentials display on the login page. I figured out that your statement ‘Notice that you don’t even need to tie the input field values to a JSF backing bean!’ doesn’t work for me. My BB, request scoped and managed by spring, will not be instantiated after AuthenticationProvider.authenticate failed on wrong credentials and redirect to login-page happens. By this the handleErrorMessage is not called via @PostConstruct.

    To solve this, i bound a BB-property username to my login-page input field. Now after Spring Security setup the BadCredentialsException in the session, i am able to process this info via @PostConstruct in handleErrorMessage.

    The only problem i am still faced with is that the instantiation of my BB occurs when jsf is already rendering the response and therefore occurs on rendering my input-field. This is by far too late, as i drop the messages on the page via h:messages long before.

    Any suggestions on how i can get the messages rendered before rendering the input field? Or better: Is it possible as you stated, to omit the binding login-page to BB – and if – how do i get the BB be instantiated this way on redirect to login-page?

  42. Lincoln says:

    Ahh yes, the Multi-Page messages issue… this is an issue with the JSF lifecycle that’s left up to us to fix :) Fortunately, it’s not hard.

    Take a look at my post here, and let me know if that helps you get your message working.

    http://ocpsoft.com/java/persist-and-pass-facesmessages-over-page-redirects/

  43. Danny Fürniß says:

    Thanks for your reply, but your suggestion did not solve my problem. I’ll try to explain the problem more clearly. After i entered the wrong username and password on my login page and submitted the form via a click on my login-button, the sequence of the method calls is as follows:
    by the way: this is the sequence without binding LoginBB.username to login.xhtml-inputText
    1. LoginBB (constructor)
    2. LoginBB.handleErrorMessage (@PostConstruct) At this time there is no BadCredentialsExc. in the session
    3. LoginBB.doLogin (calls authenticate on spring security framework) The spring security framework is now populating the BadCredentialsExc. in the session
    4. spring security sends redirect to login page

    –> No messages were displayed as the login page does not bind any inputs to the LoginBB and therefore the LoginBB is not instantiated again on the redirect. By this no FacesMessage is created.

    If i bind the login.xhtml-inputText to LoginBB.username the sequence will subsequently be continued as follows:
    5. The redirect to the login-page causes login.xhtml to be rendered.
    6. In the rendering phase jsf tries to resolve the binding and therefore constructs a new (as we have request scope) LoginBB
    7. Again handleErrorMessages is executed (now we have the BadCredentialsExc. in session and can populate a FacesMessage)
    8. inputText is rendered
    9. rendering phase finished

    –> No messages displayed, as the h:messages tag was rendered before we were able to populate the FacesMessage while rendering the inputText.

    Using the MultiPageMessageSupport PhaseListener will not solve this issue as this is a problem with the sequence.

    I figured out that if i submit the wrong credentials two times (click the login-button again) the message will secondly be displayed correctly as desired.

    Any more suggestions on this topic?

  44. Lincoln says:

    “No messages displayed, as the h:messages tag was rendered before we were able to populate the FacesMessage while rendering the inputText.”

    That’s actually not quite right. While the component may exist in the current UIViewRoot, it will not be rendered until the RENDER_RESPONSE phase, which is the last phase of processing, and occurs after the handleErrorMessages() method.

  45. redsun says:

    thanks, lincoln, everything works, except for message displaying. i’ve tried to debug phase listener and my backing bean – it works exactly in the same way as danny told before. here is output from my log:

    ===> Before phase: RESTORE_VIEW(1)
    ===> Save messages: 0 saved
    ===> After phase: RESTORE_VIEW(1)
    ===> Save messages: 0 saved
    ===> Before phase: APPLY_REQUEST_VALUES(2)
    ===> Save messages: 0 saved
    ===> After phase: APPLY_REQUEST_VALUES(2)
    ===> Save messages: 0 saved
    ===> Before phase: PROCESS_VALIDATIONS(3)
    ===> Save messages: 0 saved
    ===> After phase: PROCESS_VALIDATIONS(3)
    ===> Save messages: 0 saved
    ===> Before phase: UPDATE_MODEL_VALUES(4)
    ===> Save messages: 0 saved
    ===> After phase: UPDATE_MODEL_VALUES(4)
    ===> Save messages: 0 saved
    ===> Before phase: INVOKE_APPLICATION(5)
    ===> Save messages: 0 saved
    ===> After phase: INVOKE_APPLICATION(5)
    ===> Save messages: 0 saved
    ===> Before phase: RESTORE_VIEW(1)
    ===> Save messages: 0 saved
    ===> After phase: RESTORE_VIEW(1)
    ===> Save messages: 0 saved
    ===> Before phase: RENDER_RESPONSE(6)
    ===> Save messages: 0 saved
    ===> Load messages: 0 loaded
    ===> Bad credentials: org.springframework.security.BadCredentialsException: Bad credentials
    ===> After phase: RENDER_RESPONSE(6)

    as you can see, message couldnt’ be populated as it is added to FacesContext too late.

  46. Lincoln says:

    Try this version and see if it works for you. This works for me, so you might just have to do a little tweaking…

    http://prettyfaces.googlecode.com/files/MultiPageMessagesSupport.java

  47. Pete says:

    Was there anything conclusive in the messages not displaying? I get exactly the same behaviour as Danny Fürniß – a second click displays the message correctly and all seems well with repeated failures until a successful login is achieved followed by a logout. I am then back to the first senario where the first attempt to fail authentication displays no message. I would really love to put this one to bed – is this a viable solution (Spring Security) for securing my JSF application or not!?!

  48. Lincoln says:

    I wish I could help you two. I can’t reproduce this problem. Everything is working fine for us. Perhaps you could send a WAR file / sources to reproduce the issue? I’d be glad to take a look.

  49. Lincoln says:

    Ok… you are very correct. My fault.

    @PostConstruct occurrs too early in the Faces/Spring lifecycle, and at the point when the bean is constructed, the BadCredentialsException has not yet been created.

    Move the handleErrorMessage() method to a PhaseListener, like so:

    package uk.co.pkit.project.view.bean.login;

    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;

    import uk.co.pkit.project.view.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;
    }

    }

  50. [...] 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 [...]

  51. john says:

    Hey guys,

    I’m trying to use spring security in my applications, but I don’t know how to add the libraries.

    I’m using NetBeans 6.5, and I have the Spring MVC 2.5 plug in. Does this plug in come with Spring Security?

    Could you please help me so that I can use Spring MVC and Security in Netbeans 6.5.
    Thank you.

  52. john says:

    I was wondering if you could tell me how to add Sp. Sec. to my NetBnzz apps. I’ve downloaded the zip, but is there a way to add it as a plug in or something. I would really appreciate it. If I can’t use it in NetBnzz what IDE should I use. Thanks

  53. Derek says:

    John we don’t used Netbeans, but I would imagine that you could check under WEB-INB/Lib(raries) and see if you see a jar called spring-security. If you do then you have it. If not go here: http://sourceforge.net/project/showfiles.php?group_id=73357&package_id=270072&release_id=630203

    The zip file is just an example Eclipse project using Acegi / Spring Security. You can copy the contents of the zip file into a sample project and try and run it.

  54. john says:

    Derek, what IDE do you use? I want to learn spring framework with the spring security. I don’t know what environment to use. Can you help me with that please?

  55. Pete says:

    Hi Lincoln,

    I have incorporated Ocpsoft’s “prettyfaces” into my application and am very enjoying “pretty” names in the address bar. However, I’m finding issues with Spring Security via LoginBean, as above. After j_spring_security_check, the forward is to the unprettyfaced resource which appears distastefully in the address bar ;-(

    Do you have any ideas how to forward to the “pretty” name?

    Also, I use a prettylink to a Spring secured resource and include a request parameter, this is not forwarded on after the j_spring_security_check.

    I do very much like prettyfaces though and love the flexibility it gives. Would be great to have a solution to fully include Spring Security.

    Cheers,
    Pete

    PS code uploaded to same url as before ;-)

  56. Lincoln says:

    Update your default-target-url, etc, in the spring config.xml file:

    default-target-url="/faces/home.jsf" authentication-failure-url="/faces/login.jsf" always-use-default-target="false">

  57. [...] HttpRequestDispatcher to cause forword to /j_spring_security_check.jsp, there is one toturial on http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/ which shows how to implement [...]

  58. [...] worked for me: Acegi/Spring Security Integration – JSF Login Page By mgryszko http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/ Possibly related posts: (automatically generated)Spring security, DWR and session time outWhat I am [...]

  59. Hi,

    I need to provide form based authentication in JSF where can i write action in JSF page and how can i write web.xml file and weblogic.xml, can you some example with examples

  60. Ponic says:

    Hello,

    Good article. Any good working sample app which shows acegi with ntlm authentication?

    As I am urgently looking for one.

    Thanks

  61. atulajoshi24 says:

    Hi,

    Very good article.
    I have been questions :

    1)I am still not able to understand why LoginBean needs to be called before spring security . What is the reason for doing so ? Can you please explain ?
    2)Why is login-processing-url required in application-security ? Will it be used since login is always processed by LoginBean which forwards it to spring-security-check url .

  62. [...] whole tutorial is based on  Lincoln Baxter III‘s great tutorial. The solution – that appears in that blog entry – has been [...]

  63. LottaLava says:

    Hey, change the PhraseId from RENDER_RESPONSE to RESTORE_VIEW, then your login error will display correct!

    Very thanks for this tutorial, easy to understand and to implement, Spring and JSF rocks!

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.