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

时间:2013-01-05 21:59:51

标签: spring security httpsession

方案

  1. 我重新启动服务器和浏览器,因此没有会​​话数据。
  2. 我访问www.someurl.com公共访问页面。我的控制器通过此HttpSession session=request.getSession(true);
  3. 为我开了一个会话
  4. 点击飞往www.someurl.com/admin限制访问页面的飞机锚点链接,该页面将在新标签页中打开。 Spring Security 3拦截了这一点并对凭证提出了挑战。我成功登录。
  5. 我使用www.someurl.com返回上一个标签并刷新页面。
  6. 问题

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

    追踪情景

    1. 重新启动浏览器和服务器,因此不存在会话数据。
    2. 我去了www.someurl.com。控制器已注入请求。 request.session为null。 getSession(true)给我一个id为87B091B12F38D44C53AF0DA9E2147484的会话。 LogService获取请求对象并且也执行getSession(true)但是获取了具有id 87B091B12F38D44C53AF0DA9E2147484的会话,所以到目前为止一切都很好。
    3. 我点击/ admin。页面在新选项卡中打开。我登录。
    4. 我刷新了www.someurl.com。控制器已注入请求。 request.session不为空。会话ID为547DF59035C91783D783BAEF4A15FBFF。

2 个答案:

答案 0 :(得分:9)

你的诊断错误了:

  

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

正是因为所有页面都使用相同的会话,当您返回第一个选项卡并刷新时,您仍然以管理员身份登录。给定浏览器的所有选项卡和框架共享给定webapp的相同会话。这就是它的工作原理。服务器不知道并关心浏览器选项卡。它获取附加到给定浏览器发送的所有请求的会话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中进行身份验证的人,因为身份验证凭据存储在会话中。
  5. 编辑:看来我错了,Spring确实在登录后创建了一个新会话,以防止会话固定攻击。 the documentation

    中提供了有关其原因以及如何避免此行为的说明
      

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

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

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

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

    •   

答案 1 :(得分:3)

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

您可以通过在XML配置中创建其实例来实现,如下所示:

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

然后,您需要在spring security config中配置http元素以使用您的bean实例:

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

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

<%@ page session="false" %>