如何阻止 Spring Security 创建新会话?

Posted

技术标签:

【中文标题】如何阻止 Spring Security 创建新会话?【英文标题】:How to stop Spring Security from creating a new session? 【发布时间】:2012-12-20 01:19:18 【问题描述】:

场景

    我重新启动服务器和浏览器,所以没有会话数据。 我去 www.someurl.com 公共访问页面。我的控制器让我与此HttpSession session=request.getSession(true); 进行会话 我单击指向 www.someurl.com/admin 受限访问页面的平面锚链接,该页面在新选项卡中打开。 Spring Security 3 拦截了这一点并挑战凭据。我登录成功。 我通过 www.someurl.com 返回上一个选项卡并刷新页面。

问题

我在 www.someurl.com 的控制器中注意到的是,第 2 步和第 4 步的会话 ID 不同。看起来 Spring Security 创建了一个新会话,并且该会话现在附加到公共页面的请求。为什么会发生这种情况,我可以强制 Spring Security 使用现有会话吗?

追踪场景

    重新启动浏览器和服务器,使会话数据不存在。 我去 www.someurl.com。控制器已注入请求。 request.session 为空。 getSession(true) 让我获得一个 ID 为 87B091B12F38D44C53AF0DA9E2147484 的会话。 LogService 获取请求对象并执行 getSession(true),但获取 ID 为 87B091B12F38D44C53AF0DA9E2147484 的会话,所以到目前为止一切都很好。 我单击 /admin。页面在新标签页中打开。我登录了。 我刷新了 www.someurl.com。控制器已注入请求。 request.session 不为空。会话 ID 为 547DF59035C91783D783BAEF4A15FBFF。

【问题讨论】:

【参考方案1】:

您的诊断有误:

我在 www.someurl.com 的控制器中注意到的是,第 2 步和第 4 步的会话 ID 不同。看起来 Spring Security 创建了一个新会话,并且该会话现在附加到公共页面的请求。

正是因为所有页面都使用同一个会话,所以当您返回第一个选项卡并刷新时,您仍然以管理员身份登录。给定浏览器的所有选项卡和框架共享给定 web 应用程序的相同会话。这就是它的工作原理。服务器不知道也不关心浏览器选项卡。它获取附加到给定浏览器发送的所有请求的会话 cookie,并使用此 cookie 获取相应的会话。这实际上是一件好事。没有它,每次您打开一个已经过身份验证的新选项卡时,您都必须再次进行身份验证。而你绝对不希望这样。

那么让我们解释一下你的场景中会发生什么:

    您重新启动服务器和浏览器,因此没有会​​话数据。 您访问 www.someurl.com 公共访问页面。您的控制器会为您提供会话。将 cookie 发送回浏览器 您单击指向 www.someurl.com/admin 受限访问页面的平面锚链接,该页面在新选项卡中打开。 cookie 与请求一起发送,因此此请求是在步骤 2 中打开的会话的一部分。Spring Security 3 截获此请求并质询凭据。它将凭据附加到会话,该会话现在是经过身份验证的会话 您通过 www.someurl.com 返回上一个选项卡并刷新页面。 cookie 再次发送,Spring 知道您是在第 3 步进行身份验证的人,因为身份验证凭据存储在 session 中。

编辑:看来我错了,Spring 确实在登录后创建了一个新会话以防止会话固定攻击。 the documentation 中提供了有关此功能为何有用以及如何避免此行为的说明:

会话固定攻击是一种潜在风险,恶意攻击者可能通过访问站点来创建会话,然后说服其他用户使用相同的会话登录(通过向他们发送包含会话标识符的链接作为参数,例如)。 Spring Security 通过在用户登录时创建一个新会话来自动防止这种情况发生。如果您不需要此保护,或者它与其他一些要求冲突,您可以使用 session-fixation-protection 属性控制该行为三个选项

migrateSession - 创建一个新会话并将现有会话属性复制到新会话。这是默认设置。

无 - 不做任何事情。原始会话将被保留。

newSession - 创建一个新的“干净”会话,而不复制现有会话数据。

【讨论】:

我从来没有想过这可能是会话保护的副作用。谢谢。【参考方案2】:

您需要更改HttpSessionRequestCache 的行为,以便在不存在会话时它不会创建会话。

您可以通过在您的 XML 配置中创建它的实例来做到这一点,如下所示:

<beans:bean id="httpSessionRequestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"> 
    <beans:property name="createSessionAllowed" value="false" /> 
</beans:bean>

然后你需要在你的 spring 安全配置中配置 http 元素来使用你的 bean 实例:

<http auto-config="true" ....> 
    <request-cache ref="httpSessionRequestCache"/> 
    ... rest of your config
</http>

如果您使用 JSP,您还应该阻止 JSP 创建会话。为了做到这一点,您需要在每个 JSP(甚至包括从其他 JSP 中包含的那些)之上添加一个 page 指令。

<%@ page session="false" %>

【讨论】:

&lt;%@ page session="false" %&gt; 帮助了我。

以上是关于如何阻止 Spring Security 创建新会话?的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot + spring security - 如何阻止应用层上的CORS请求?

如何在 Spring Security 中阻止 LDAP 用户帐户而不锁定 LDAP 用户?

带有 permitAll() 和过期身份验证令牌的 URL 的 Spring Security

新会话的Spring安全创建

尽管有 SecurityConfig,但 Spring Security 会阻止 POST 请求

Spring-security 阻止匿名用户从 MongoDB 中提取数据