3

设想

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

问题

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

追踪场景

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

2 回答 2

11

您的诊断错误:

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

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

因此,让我们解释一下您的场景中会发生什么:

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

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

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

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

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

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

于 2013-01-05T22:08:58.080 回答
3

您需要更改 的行为,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 创建会话。为了做到这一点,您需要在每个 JSPpage之上添加一个指令(甚至包括从其他 JSP 中包含的那些)。

<%@ page session="false" %>
于 2013-01-05T23:40:10.470 回答