Aubergine
Aubergine

Reputation: 6042

Spring MVC strange behavior

I have a method that handles request with a URI of "/home". This request is generated upon successful log-in procedure. Here is a little code to support my situation:

<security:form-login login-processing-url="/static/j_spring_security_check"
login-page="/login" authentication-failure-url="/login?login_error=t"
default-target-url="/home"/> 

The method body demonstrates what I am attempting to achieve:

String userMail = SecurityContextHolder.getContext().
    getAuthentication().getName();
logger.info(userMail);

Person p = userService.retrieveUserByEmail(userMail);
session.setAttribute("person", p);

return "user/home";

This bit is important as the person p is used as data source for other requests.

Now the problem. I don't know if it is the property of Google Chrome, but for some reason the browser remembers the request you've done before log-in and instead of going through /home request after successful log-in procedure, it generates the previous request bypassing this /home gate, resulting in null pointer exception as person p was never set up, as session wasn't populated by /home request.

I know that for other requests I should do validation, but I don't like the idea of letting user generate any request without prior going through /home .

Done with text description and now to explain how I get unwanted behaviour in steps:

  1. ask for request that you know exist such as: myApp/nameOfSomething/viewThisSomething - you are brought to log-in page as expected(you must be authenticated for request to be accepted)

  2. you enter correct credentials and instead of going to default-target-url="/home" you are automatically making previous request myApp/nameOfSomething/viewThisSomething without populating session with necessary data and resulting in nullpointer exception.

What else is interesting is that logger shows the mail, so it might be that they are both executed at the same time but /home request is slower - can that happen?

I resolve the situation in other method by checking if null and forcing to go back to /home which works as expected, but I am control freak and don't like when user is doing what he is not intended to do.

Thank You for Your time,

Upvotes: 1

Views: 138

Answers (1)

JB Nizet
JB Nizet

Reputation: 691785

It's not a bug, it's a feature. It's much more user-friendly to let the user go where he wants to go after login than forcing him to go to the home page. He could have bookmarked one of the protected pages, or simply browsed some non-protected pages containing a link to a protected page.

From http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-form-target:

If a form login isn't prompted by an attempt to access a protected resource, the default-target-url option comes into play. This is the URL the user will be taken to after successfully logging in, and defaults to "/". You can also configure things so that the user always ends up at this page (regardless of whether the login was "on-demand" or they explicitly chose to log in) by setting the always-use-default-target attribute to "true"

IMHO, you should keep things as is, but make sure that the required sesion attribute is set once the login is successful, instead of setting this attribute in the home page. This would ensure that every protected page has access to the session attribute, even if the user didn't go to the home page.

You could do this easily by using a custom UsernamePasswordAuthenticationFilter subclass, that sets the appropriate attribute in session once the authentication has succeeded.

Upvotes: 2

Related Questions