我不知道使用什么SecurityContextHolder策略

时间:2012-04-17 12:25:24

标签: java spring spring-security security-context

我使用此类代码进行身份验证:

@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";
    }
}

我可以登录,它有效。我在日志中看到not-null身份验证对象。 然后我尝试浏览一些像这样的安全页面:

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

由于getAuthentication(),它会抛出NullPointerException。 当我使用SecurityContextHolder.MODE_INHERITABLETHREADLOCAL和SecurityContextHolder.MODE_INHERITABLETHREADLOCAL时,会发生这种情况,这与使用SecurityContextHolder.MODE_GLOBAL不同。

我做错了什么?我不需要SecurityContextHolder的MODE_GLOBAL行为。

UPD:有时会出现问题,有时会出现在同一会话中。

1 个答案:

答案 0 :(得分:1)

通过记录确保安全过滤器每次都在您的请求中运行:

request.getAttribute("__spring_security_scpf_applied");

不要。除非你完全知道你在做什么,否则不要替换SecurityContextHolderStrategy。它与查找基于ThreadLocal的SecurityContext有关。因此,除非你是一个非常奇怪的Servlet容器,否则默认情况几乎总是正确的。

您还需要为请求路径创建拦截器。 @PreAuthorize仅适用于方法调用http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html,这不是您想要的。

相反,您需要在安全应用程序上下文中使用以下内容:

<http> ...
        <intercept-url pattern="/user**" access="hasRole('user')" />
</http>