使用 Spring Security 时请求之间是不是共享 SecurityContext?
Posted
技术标签:
【中文标题】使用 Spring Security 时请求之间是不是共享 SecurityContext?【英文标题】:Is a SecurityContext shared between requests when using Spring Security?使用 Spring Security 时请求之间是否共享 SecurityContext? 【发布时间】:2015-08-25 23:57:03 【问题描述】:在使用 Spring Boot 编写的 rest API 上使用基于无状态令牌的身份验证时,我看到了一些奇怪的行为。
客户端在每个请求中都包含一个 JWT 令牌,并且我编写的扩展 GenericFilterBean 的自定义过滤器使用以下内容将基于令牌中的声明的身份验证对象添加到安全上下文:
SecurityContextHolder.getContext().setAuthentication(authentication);
并在处理请求后清除上下文:
SecurityContextHolder.getContext().setAuthentication(null);
但是,当我开发的简单应用程序执行一系列操作时,我有时会发现安全上下文设置不正确 - 有时它对于提供令牌的请求为空。过滤器被正确调用,setAuthencation() 也被调用,但请求认证失败,并抛出 403 denied。
如果我通过将会话创建策略设置为 STATELESS 来明确关闭任何 http 会话管理,则此行为将停止。
有什么想法可以在这里发生吗?是否以某种方式在处理请求的线程之间共享安全上下文?
【问题讨论】:
你检查了吗? ***.com/questions/16952718/… 【参考方案1】:根据此处的官方文档,似乎可以共享上下文: http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html
在单个会话中接收并发请求的应用程序中,相同的 SecurityContext 实例将在线程之间共享。即使使用了 ThreadLocal,它也是从每个线程的 HttpSession 中检索到的同一个实例。如果您希望临时更改线程正在运行的上下文,这会产生影响。如果您只使用 SecurityContextHolder.getContext(),并在返回的上下文对象上调用 setAuthentication(anAuthentication),那么 Authentication 对象将在共享相同 SecurityContext 实例的所有并发线程中发生变化。您可以自定义 SecurityContextPersistenceFilter 的行为,为每个请求创建一个全新的 SecurityContext,防止一个线程中的更改影响另一个线程。或者,您可以在临时更改上下文的位置创建一个新实例。 SecurityContextHolder.createEmptyContext() 方法总是返回一个新的上下文实例。
【讨论】:
以上是关于使用 Spring Security 时请求之间是不是共享 SecurityContext?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Security 时,oauth 范围和角色之间有啥区别吗? [复制]
Spring Security Oauth - 发送令牌请求时需要基本访问身份验证
使用 Spring Security 登录:不支持请求方法“POST”
在进行跨域请求时,如何使用 SockJS 和 STOMP 添加 Spring Security JSESSIONID?