问题
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.
回答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>
来源:https://stackoverflow.com/questions/10191232/i-dont-know-what-securitycontextholder-strategy-to-use