当我的会话创建策略设置为 STATELESS 时,为啥 Spring Security 的 SessionManagementFilter 会运行?
Posted
技术标签:
【中文标题】当我的会话创建策略设置为 STATELESS 时,为啥 Spring Security 的 SessionManagementFilter 会运行?【英文标题】:Why is Spring Security's SessionManagementFilter running when my session creation policy is set to STATELESS?当我的会话创建策略设置为 STATELESS 时,为什么 Spring Security 的 SessionManagementFilter 会运行? 【发布时间】:2018-11-21 19:35:00 【问题描述】:我有一个使用 Spring Security 4.0.1.RELEASE 的基于 J2EE REST 的 Web 应用程序。我正在使用基于 Java 的配置配置 Spring Security,并将会话创建策略设置为 STATELESS,如下所示:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(secureEnabled=true, prePostEnabled=true, jsr250Enabled=true, order=1)
public class DefaultSecurityBeansConfig extends WebSecurityConfigurerAdapter
// ...
@Override
protected void configure(HttpSecurity http) throws Exception
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()...; // additional config omitted for brevity
// ...
// ...
在阅读了this article 关于 Spring Security 会话管理的内容后,我相信 SessionManagementFilter
过滤器应该不在 Spring Security 的过滤器链中运行。但这绝对是。我可以在该类的 doFilter
方法中设置断点,它会在对服务器的每个请求上运行。
这里发生了什么?这个过滤器正在运行的事实导致了我的应用程序中的其他意外行为,我认为这些行为已经被配置了。
谢谢。
【问题讨论】:
你的理解是错误的。它仍然会运行,但不会创建会话或在会话中存储内容。将有一个SessionManagementFilter
和一个 NullSecurityContextRepository
不会存储它。所以基本上它会一直运行,但取决于配置它会做些什么。
好吧,这有点道理。但是当它运行时,它几乎不是空操作。 doFilter
方法调用onAuthentication
方法,该方法已将ChangeSessionIdAuthenticationStrategy
注册为其唯一的委托策略。这似乎与我的STATELESS
会话创建策略相冲突。我没有明确设置会话固定策略,如果我没记错的话将默认为migrateSession
,但这种行为意味着我以某种方式使用changeSessionId
。我最终可能会针对这些发现发布一个新问题。
这不应该是一个问题,因为您没有创建会话(至少 Spring Security 没有创建会话,这并不意味着没有其他东西在创建会话! ) 这基本上应该是一个 noop。由于该策略首先检查是否已经存在会话,如果没有,则什么也不做。 Spring Security 在无状态模式下运行的事实并不意味着您的应用程序的其余部分会自动变为无状态!
可以肯定的是,我的应用程序正在使用始终运行的 servlet 过滤器 (((HttpServletRequest) request).getSession()
) 创建会话。而这个正在运行的ChangeSessionIdAuthenticationStrategy
不断改变我的JSESSIONID。根据 Spring 文档,SessionCreationPolicy
的 NEVER 值应该使用HttpSession
(如果存在),而 STATELESS 值“将永远不会创建 HttpSession 并且永远不会使用它来获取 SecurityContext
”。对我来说,这听起来不应该与我的 JSESSIONID 混淆。我真的很困惑为什么它会干扰。
这是有干扰的,因为在无状态模式下运行和防止会话固定攻击是两件不同的事情。这里发生的是 Spring Security 检测会话,默认情况下,用于防止会话劫持的安全性是更改会话 ID。如果您不希望通过sessionFixation().none()
将其指定为无。但是,这将使您的应用程序不那么安全并且容易受到会话固定攻击。我不明白为什么更改 sessionid 会破坏事情,修复破坏的内容而不是降低您的应用程序的安全性。
【参考方案1】:
使用 Spring Security 时,会话管理比在会话中存储经过身份验证的用户更广泛(如 Spring Security 指南的 Session Management Section 中所述)。
HTTP 会话相关功能由过滤器委托给的
SessionManagementFilter
和SessionAuthenticationStrategy
接口组合处理。典型用途包括会话固定保护攻击预防、会话超时检测以及对经过身份验证的用户可以同时打开多少会话的限制。
说sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
并不意味着您的应用程序是无状态的,这意味着Spring Security 不会创建会话。如果您的应用程序中还有其他东西仍在创建会话,Spring Security 将尝试保护它免受会话固定攻击。
如何进行会话固定攻击取决于配置的策略;默认是更改每个请求的会话标识符。在 Servlet 3.1 和更新的容器中,如果没有进行显式配置,ChangeSessionIdAuthenticationStrategy
是默认值。在 Servlet 3.0 及以下版本中,默认为migrateSession
。
您可以通过执行sessionFixation().none()
来禁用会话固定保护;但是,您必须质疑这是否是您真正想要的,因为这可能会降低您的应用程序的安全性。
根据什么中断/失败,您可能想要修复它而不是降低您的应用程序的安全性。
【讨论】:
以上是关于当我的会话创建策略设置为 STATELESS 时,为啥 Spring Security 的 SessionManagementFilter 会运行?的主要内容,如果未能解决你的问题,请参考以下文章
当从 android 访问 API 时,sails.js 会话变量会丢失