Announcement Announcement Module
Collapse
No announcement yet.
Cookies in ServletRequest from previous browser requests Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Cookies in ServletRequest from previous browser requests

    Hello,

    I am having an odd problem and it took me some time to track it down. I am now able to reproduce it 100% but am not sure what the solution is to the problem.

    Background... I have a Spring MVC (3.0.0) project setup using Spring Security (3.0.0). I originally built up the project using Spring Roo (1.0.0). After initial creation through Roo, the applicationContext-security.xml was modified so that a custom login and logout success handler could be used.

    Code:
    	<http auto-config="true" use-expressions="true">
    		<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" authentication-success-handler-ref="myAuthenticationHandler" />
    		<logout logout-url="/static/j_spring_security_logout" success-handler-ref="logoutHandler" />
    
    		...
    	</http>
    
    	<beans:bean id="logoutHandler" class="com.myproject.web.LogoutHandler" />
    	
    	<beans:bean id="myAuthenticationHandler" class="com.myproject.web.MyAuthenticationHandler" />
    The MyAuthenticationHandler class is responsible for creating a custom token cookie that is used within the application. Relevant code from the class is:

    Code:
    ...
    
    public class MyAuthenticationHandler implements ServletContextAware, AuthenticationSuccessHandler
    {
    ...
    
    	@Override
    	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
    	{
    	...
    		response.addCookie(createCookie(CUSTOM_TOKEN_KEY, encodedToken));
    
    		response.sendRedirect(servletContext.getContextPath() + "/logged-in");
    	}
    ...
    
    }
    The LogoutHandler class just deletes the cookie on successful logout.

    Code:
    	@Override
    	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
    	{
    		Cookie token = new Cookie(CUSTOM_TOKEN_KEY, null);
    		token.setMaxAge(0);
    		token.setPath(servletContext.getContextPath());
    		response.addCookie(token);
    		
    		response.sendRedirect(servletContext.getContextPath());
    	}
    The last piece of code of importance is the controller that is acting on the main page being displayed.

    Code:
    @RequestMapping("/index")
    @Controller
    public class MyController
    {
    ...
    
    	@RequestMapping
    	public String get(@CookieValue(value = CUSTOM_TOKEN_KEY, required = false) String customToken, Model model, HttpServletRequest request)
    	{
    		if (customToken != null) // breakpoint is on this line
    		{
    			// process custom token and add data to the model
    		}
    		else
    		{
    			SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
    			SecurityContextHolder.clearContext();
    		}
    		
    		return "index";
    	}
    ...
    }
    The problem I am running into is that when I debug the Controller, and it breaks on the breakpoint, information showing up in the HttpServletrequest object for the cookie is not correct. Here is an example of how I reproduce the problem:

    1. Enter URL for main page.
    2. Page redirects to login page. Browser cookie has jsessionid of 721860F1066A12381203EA6F71E63C1A
    3. Login successful and redirected to logged-in page. Browser cookie has jsessionid of 1DCE1745DBEAD34281355FFD4E97EB14 and the custom token cookie exists.
    4. Click link to main page.
    5. Breakpoint on main page controller is hit and HttpServletRequest has cookie for jsessionid as 4CF46F79D2487236A12F9E27EEE1392E but no custom token cookie.
    6. Controller logs out player as custom token cookie doesn't exist.
    7. Click link to go to main page again (or refresh page).
    8. Page redirects to login page. Browser cookie has jsessionid of 1DCE1745DBEAD34281355FFD4E97EB14
    9. Login successful and redirected to logged-in page. Browser cookie has jsessionid of B1C80DDCCC5FD4725DA234EDAD91AA0 and the custom token cookie exists.
    10. Click link to main page.
    11. Breakpoint on main page controller is hit and HttpServletRequest has cookie for jsessionid as 1DCE1745DBEAD34281355FFD4E97EB14 and custom token cookie.
    12. Controller adds information to the model, based on information in custom token cookie, and the main page views properly.
    13. Click logout link.
    14. Redirected to login page. Browser cookie has jsessionid of 8B6FDC7F3A8E657DB44A9C7AB93F8532 and custom token cookie is deleted as part of logout process.
    15. Login successful and redirected to logged-in page. Browser cookie has jsessionid of 2920EA0E139EACA83AB20F248480D6E1. Custom token cookie exists.
    16. Click link to go to main page.
    17. Main page controller has request cookie for jsessionid as B1C80DDCCC5FD4725DA234EDAD91AA0B but no custom token cookie.


    At this point I can continue to loop through the testing by repeating steps 6 to 17. Each time the jsessionid's will have the same consistency and the custom token cookie will exist / not exist in the same spots. What I expected to happen on the same steps is:

    1. Enter URL for main page.
    2. Page redirects to login page. Browser cookie has jsessionid of <RandomJSessionID111>
    3. Login successful and redirected to logged-in page. Browser cookie has jsessionid of <RandomJSessionID222> and the custom token cookie exists.
    4. Click link to main page.
    5. Breakpoint on main page controller is hit and HttpServletRequest has cookie for jsessionid as <RandomJSessionID222> and custom token cookie.
    6. Controller adds information to the model, based on information in custom token cookie, and the main page views properly.

    I am not sure how the Spring MVC is returning request cookies for requests other than the current request. I have confirmed that the browser is sending the proper cookies along with the request to each page. The only thing I can think is causing problems is I am not doing something correct in my login success handler and as such the request isn't being consumed properly and is still available for the next controller to pickup. It feels like the server is one request behind which is a little scary as that would lead to data polution between sessions.

    I have posted this in the Spring Security forum as I think the problem is related to my handlers but it may be a Spring MVC issue. If so please let me know so I can post it there as well.

    Thanks

  • #2
    Have You found the solution yet?

    Comment


    • #3
      I have almost solved this but don't know how to do it. Here is a little more information on my problem.

      I was able to walk through the call stack to see if the cookie was in the original request and when that cookie was being ignored. I found the problem with the HttpSessionRequestCache in regards to the SavedRequest. The cache is pulling the saved request from the initial call to the main page and using that after being authenticated. The initial call to the main page doesn't have the custom token cookie so when the SavedRequest is being passed along instead of the new Request there is no cookie and the controller invalidates the authenticated session. Now when the user refreshes the page the request contains the custom token cookie but the user is not authenticated so the request is saved and the user is redirected to the login page. The user logs in and goes back to the main page. The HttpSessionRequestCache pulls out the SavedRequest with the custom token cookie and everything looks fine. This is how we were seeing odd jsessionid's within the request as the HttpSessionRequestCache was replacing the current request with a SavedRequest.

      Now with that understanding I am wondering why the SavedRequest is even being kept after the user is redirect to another page. The flow of my web site for this test is:

      main page -> login -> logged-in page -> main page

      The last step of that chain is a manual step where the user is clicking a link to get back to the main page from the logged-in page. Shouldn't the SavedRequest be removed as soon as the user is redirect to the logged-in page?

      My dilemma is I am not sure how to go about fixing this problem. I understand some of the basis for having the SavedRequest so that you can redirect a user right back to what they were doing after being logged in. For my application though this won't work as we add that cookie to the request so we can never use the SavedRequest once they are authenticated. Would I have to create a custom filter chain that doesn't include the RequestCacheAwareFilter?

      Any help would be appreciated.

      Thanks

      Comment


      • #4
        Submitted a ticket as I thought that there may be a bug within the SavedRequest cache system. Based on the ticket I was enlightened to the fact that if I am doing a custom success handler I should also be aware of the SavedRequest and removing it myself if needed.

        https://jira.springsource.org/browse/SEC-1408

        The code for SavedRequestAwareAuthenticationSuccessHandler within the Spring Security library has an example of how to get the requestCache object to be able to remove the request.

        Comment

        Working...
        X