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

场景

  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. 我单击 /admin。页面在新标签页中打开。我登录了。
  4. 我刷新了 www.someurl.com。控制器已注入请求。 request.session 不为空。会话 ID 为 547DF59035C91783D783BAEF4A15FBFF。

【问题讨论】:

    标签: spring security httpsession


    【解决方案1】:

    您的诊断有误:

    我在 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 中。

    编辑:看来我错了,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; 帮助了我。
    猜你喜欢
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 2022-01-01
    • 2020-06-02
    • 2011-08-19
    • 2016-03-03
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多