0

I use such code for authentication:

@PreAuthorize("isAnonymous()")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doLogin(HttpServletRequest request) {
    try {
        Authentication req = new UsernamePasswordAuthenticationToken(request.getParameter("name"),
                request.getParameter("password"));
        Authentication result = authenticationManager.authenticate(req);
        SecurityContextHolder.getContext().setAuthentication(result);
        logger.debug("Success login");
        logger.debug(SecurityContextHolder.getContext().getAuthentication());
        return "index";
    } catch (AuthenticationException e) {
        e.printStackTrace();
        logger.debug("ACHTUNG! Success failed");
        return "index";
    }
}

I can log in, it works. I see not-null Authentication object in logs. Then I try to browse some secured page like this:

@PreAuthorize("hasRole('user')")
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String user(ModelMap modelMap) {
    modelMap.addAttribute("user", SecurityContextHolder.getContext().getAuthentication().getCredentials().toString());
    return "index";
}

And it throws NullPointerException because of the getAuthentication(). This occurs when I use SecurityContextHolder.MODE_INHERITABLETHREADLOCAL and SecurityContextHolder.MODE_INHERITABLETHREADLOCAL unlike using of SecurityContextHolder.MODE_GLOBAL.

What am I doing wrong? I don't need MODE_GLOBAL-behavior of SecurityContextHolder.

UPD: Sometimes problem occurs, sometimes doesn't in the same session.

Vladyslav Lubenskyi
  • 527
  • 1
  • 7
  • 17
  • Make sure that your `/login` page isn't configured with `filters = "none"`: http://stackoverflow.com/questions/3923296/user-granted-authorities-are-always-role-anonymous – axtavt Apr 17 '12 at 12:32
  • Are you sure the NPE is coming from the result of getAuthentication() (e.g. that the Authentication object is null)? Is this in the same request in which you log in, or after you are redirected from the login page? – Peter Mularien Apr 17 '12 at 14:25
  • @peter Yes, i checked. NPE caused by getAuthentication().No, different requests. – Vladyslav Lubenskyi Apr 17 '12 at 14:48
  • As @axtavt mentioned this is almost always because the security filter is not running before the request. I would set a break point or do stack dump right before the NPE and then look at the call stack to see if the Security filters are even in the callstack. – Adam Gent Apr 17 '12 at 15:30

1 Answers1

1

Make absolutely sure that the Security Filter is running each time in your request by logging:

request.getAttribute("__spring_security_scpf_applied");

Do not. Do not replace the SecurityContextHolderStrategy unless you absolutely know what your doing. It has to do with finding the SecurityContext based on ThreadLocal. So unless your a very weird Servlet Container the default is almost always correct.

You also need to make an interceptor for your request path. The @PreAuthorize only applies to method calls http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html which is not what you want.

Instead you want something like the following in your security application context:

<http> ...
        <intercept-url pattern="/user**" access="hasRole('user')" />
</http>
Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • 1
    Upvoting because the tip on checking the SCPF applied attribute is a great suggestion, and applicable to many questions - nice tip! – Peter Mularien Jul 25 '12 at 17:17