情境


我重新启动服务器和浏览器,所以没有会话数据。
我访问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不为null。会话ID为547DF59035C91783D783BAEF4A15FBFF。

最佳答案

您的诊断错误:


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


正是因为所有页面都使用相同的会话,所以当您返回第一个选项卡并刷新时,您仍以管理员身份登录。给定浏览器的所有选项卡和框架都针对给定Webapp共享同一会话。就是这样。服务器不知道也不关心浏览器选项卡。它获得一个会话cookie,该cookie附加到给定浏览器发送的所有请求中,并使用此cookie获取相应的会话。这实际上是一件好事。否则,每次您打开一个新的标签页后,就必须再次进行身份验证。而且您绝对不想要那样。

因此,让我们解释一下您的情况如何:


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


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


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


migrateSession-创建一个新会话,并将现有会话属性复制到新会话。这是默认值。
无-不执行任何操作。原始会话将保留。
newSession-创建一个新的“干净”会话,而不复制现有会话数据。

10-07 19:40