【问题标题】:I don't know what SecurityContextHolder strategy to use我不知道使用什么 SecurityContextHolder 策略
【发布时间】:2012-04-17 12:25:24
【问题描述】:

我使用这样的代码进行身份验证:

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

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

@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:有时会出现问题,有时不会出现在同一个会话中。

【问题讨论】:

  • 确保您的/login 页面未配置filters = "none": stackoverflow.com/questions/3923296/…
  • 您确定 NPE 来自 getAuthentication() 的结果(例如,Authentication 对象为空)?这是在您登录的同一个请求中,还是在您从登录页面重定向之后?
  • @peter 是的,我查过了。由 getAuthentication() 引起的 NPE。不,不同的请求。
  • 正如@axtavt 提到的,这几乎总是因为安全过滤器在请求之前没有运行。我会在 NPE 之前设置一个断点或进行堆栈转储,然后查看调用堆栈以查看安全过滤器是否在调用堆栈中。

标签: java spring spring-security security-context


【解决方案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>

【讨论】:

  • 赞成,因为检查SCPF应用属性的提示是一个很好的建议,适用于许多问题-很好的提示!
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 2023-03-30
  • 2022-06-26
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
相关资源
最近更新 更多