Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security "forward:" directive can't forward to login form

After a user creates their account, I want to log that user on automatically.

I have standard form logins being handled by Springs filter on /postlogin. If I go to http://localhost/postlogin it attempts to log me in (fails because I didn't include the post parameters), but makes the proper attempt.

But if I want to log the user in programatically and I try to return from the controller: "forward:/postlogin" I get a 404.

I assume the forward: directive is not passing through the filters, thus not getting handled by the UsernamePasswordAuthenticationFilter.

How do I manually induce a login programatically? I want to do this after the user creates a new account (they should be logged into that account immediately upon completion of the registration).

like image 624
David Parks Avatar asked Jan 28 '11 02:01

David Parks


2 Answers

I mis-read another piece of guidance and realized that the correct way of handling this is the following:

1) Manually set the Authentication token on SecurityContextHolder

    UsernamePasswordWithAttributesAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( loadUserByUsername(username), password, authorities );
    SecurityContextHolder.getContext().setAuthentication(authenticationToken);

2) Do Not render a page at this point or use the forward: directive. You must use the redirect: directive.

return "redirect:/accountcreated";

If you render a page the page will load fine, but the session object will be lost because a new j_session_id will be created but will not make it to the browser mid-request and the next request will use the old j_session_id, loosing the new session object & authetication.

Using the forward: directive will bypass the authentication filters, no good.

But redirect: causes the updated session information to make it to the browser.

like image 74
David Parks Avatar answered Sep 30 '22 02:09

David Parks


The new filtering feature in Servlet 2.4 basically alleviates the restriction that filters can only operate in the request flow before and after the actual request processing by the application server. Instead, Servlet 2.4 filters can now interact with the request dispatcher at every dispatch point. This means that when a Web resource forwards a request to another resource (for instance, a servlet forwarding the request to a JSP page in the same application), a filter can be operating before the request is handled by the targeted resource. It also means that should a Web resource include the output or function from other Web resources (for instance, a JSP page including the output from multiple other JSP pages), Servlet 2.4 filters can work before and after each of the included resources. .

To turn on that feature you need:

web.xml

<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>/<strike>*</strike></url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

RegistrationController

return "forward:/login?j_username=" + registrationModel.getUserEmail()
    + "&j_password=" + registrationModel.getPassword();
like image 41
AlexK Avatar answered Sep 30 '22 02:09

AlexK