ASP.NET会话ID在浏览器选项卡之间共享

9

最近我正在使用asp.net webforms开发一个网站,它使用in proc sessions。我注意到会话ID在浏览器选项卡之间共享。因此,我想知道以下情况你会怎么做:

问题:在同一浏览器中多次登录不同用户的问题。

  1. 用户在浏览器选项卡1中打开网站并登录为"user1" - 存储在session中
  2. 用户在浏览器选项卡2中打开网站并登录为"user2" - 存储在session中
  3. 此时,由于session ID在浏览器选项卡之间共享,会话信息现在指向"user2"
  4. 用户在选项卡1上尝试操作,结果突然显示"user2"的信息

如何在选项卡1中提醒用户已更改或如何强制选项卡1用户注销?

我的初步想法是通过数据库或应用程序对象保持具有会话ID的活动用户列表,但我面临的问题是,在选项卡1中,我将用什么来与该列表进行比较?当我发出请求时,HttpContext.Current.User会更新为"user2",我如何知道浏览器选项卡1最初是为"user1"而打开的?

感谢任何人让我知道上述问题的任何替代方法或最佳实践

敬礼DotnetShadow


请检查此链接:https://dev59.com/0nNA5IYBdhLWcg3wa9Kp - Muhammad Akhtar
6个回答

7
为什么不在用户2登录时发出警告呢?可以用类似这样的消息:"您已经作为用户1登录,确定要再次以另一个用户身份登录吗?"

那似乎是合理的,我想在选项卡1中没有太多可以做的。 - DotnetShadow

2

浏览器中的所有选项卡都属于同一个实例,因此所有选项卡共享cookie和会话,这方面你几乎无能为力。如果你非常想要实现这个功能,唯一能想到的解决方案是在每个URL中携带一个唯一的会话ID。基于这个唯一ID,您可以链接到特定的用户。您需要自定义会话逻辑,并确保网站中的所有链接都携带这个唯一ID。虽然可以付出很多努力来完成它,但真正的问题是,这样做是否值得呢?


这已经内置在许多网络框架中(并且不错)。通常称为无cookie身份验证,URL身份验证或类似的东西。 - bzlm
@Eamon 怎么说呢?“在每个URL中携带一个唯一的会话ID”听起来就像是无cookie会话的典型实现。 - bzlm
看我的回答,但基本上,您在URL中既有cookie又有ID。仅使用URL存储ID不太安全且不太人性化,因为URL更长;特别是因为您可能希望会话ID在路径中首先出现。尽管如此,这仍然是一个极其实用的解决方案,但存在实际差异。 - Eamon Nerbonne
@Eamon 在这个回答中,“基于那个唯一的ID,你可以链接到一个特定的用户”这句话听起来像是在描述无cookie会话。否则,会话cookie已经可以用来“链接到一个特定的用户”。只有@Sabeen知道! - bzlm
要明确一点,我实际上是指无 cookie 会话,因为我们不能再次依赖 cookie。另一个解决方案可能是具有特定文件夹路径的 cookie。在某人验证后,您将其发送到 site.com/user/whatever,这可能比在整个站点上使用唯一 ID 更容易实现。 - Sabeen Malik
显示剩余4条评论

2

有些人建议在URL中添加唯一标识符,并基于这些标识符进行跟踪。

如果你打算这样做,那么你最好让ASP.Net帮你完成这个工作,方法是打开cookieless sessions,然后使用URL来包含会话ID。


一些与编程有关的内容 - 没有 Cookie 的会话更容易受到会话劫持攻击,并且具有更长、不易读取的 URL。 - Eamon Nerbonne
@Eamon - 好的,你和Sabeen。我也链接了一篇描述优缺点的文章。 - Damien_The_Unbeliever
确实如此,并且无cookie会话肯定是一个简单的替代方案,这本身就是一种优点- +1。然而,出于上述原因,我对纯无cookie方法并不太感兴趣。 - Eamon Nerbonne

1

这就是现实。你无法改变太多。用户已经习惯了这种行为,因为像Gmail等著名的互联网站都保持着一致性...所以对他们来说不应该是什么大问题。


我的唯一担忧是,如果您在需要提交数据的页面上。最初,在提交之前,该页面被呈现为user1,如果在登录tab2并切换回tab1后,用户现在按下提交按钮,它将以user2为目标进行提交,不是吗? - DotnetShadow

1

为了避免这个问题,我会重定向并附加一个短的、随机的URL登录标识符。

然后,我不直接使用session,而是在随机的in-url代码下将一个强类型对象存储在session变量中,并使用对象进行会话存储。如果您想保持简单,可以使用字典。除了正常的会话超时之外,您还应该跟踪每个登录ID中的最后使用情况,并手动超时会话,以防止新用户保持旧登录状态。

因此,每个ASP.NET会话对应于任意数量的登录会话。

这样做有以下优点:

  • 你可以同时登录多个用户。对于许多网站来说,这非常方便。
  • 在公共终端上,它有助于避免意外的会话劫持。当一个用户离开公共终端时,关闭了Web应用程序选项卡但没有关闭浏览器(这是相当普遍的情况),另一个人接近该终端并打开一个新窗口或选项卡到您的站点时,这个新用户看不到先前登录的用户的任何痕迹。当然,用户应该注销,任何人都可以检查历史记录,但没有理由邀请滥用。
  • 对于你的网站而言,CSRF攻击会更加困难,因为没有随机登录ID的URL是没有意义的。
  • 如果使用哈希表,实现起来非常简单-毕竟,任何会话状态消费者已经编写了从哈希表中存储和检索数据的代码,您只需要更改它正在使用的哈希表,并最好包括自定义超时。

明显的缺点是您需要在URL中包含随机代码,并且需要进行一些额外的实现。您可以使用iframe和/或基于javascript + XHR的站点来隐藏额外的代码,但这样做对站点的影响更大。最后,请注意,无cookie会话不同;虽然它们更容易打开,但它们涉及一个更长的、不太人性化的URL令牌,并且由于缺乏正常的cookie会话令牌,也比会话劫持更不安全(因为突然发现会话ID的任何其他程序甚至机器都可以假装成该用户)。


您可以使用相对URL,例如。 或者,将当前会话的完整路径作为助手变量暴露在某个地方,并使用该变量来组成URL。毕竟,您需要做类似的事情来处理Web应用程序根 - 对吗? - Eamon Nerbonne
如果你正在使用 ASP.NET MVC 或者 Routing,举个例子,你可以直接将会话 ID 作为所有路由的第一个组件。 - Eamon Nerbonne
这当然是可行的,但可能有些过度 - 你不能在创建链接时控制链接前缀吗?或者如果链接是静态的,只需使用相对链接即可。 - Eamon Nerbonne
听起来不错,只是我有点困惑我的/app/relative/absolute/path是在试图说什么,跟随其中任意一个? 所以,如果我的路径是http://localhost/foo/secure/page1.aspx 它应该翻译为http://localhost/foo/TOKEN/secure/page1.aspx? - DotnetShadow
如果你从http://localhost/iisApp/TOKEN/page1.aspx导航到http://localhost/iisApp/page2.aspx,那么在浏览器端,用户仍然可以点击返回并检索TOKEN,在服务器端,您可能能够从引用中提取它。如果您然后转到http://localhost/iisApp/page3.aspx,用户仍然可以点击返回,但服务器真的很倒霉:当然它可以使用一些启发式方法(例如,如果只有一个令牌,或者如果它存储了整个历史记录并且后退链接链是唯一的,或类似的事情)。但无论如何都不是轻而易举的,而且*你*编写了服务器... - Eamon Nerbonne
显示剩余7条评论

0

把数据存储在视图状态中怎么样?这对每个窗口来说都是独一无二的。


为什么这个被踩了?实际上,它比使用无 cookie 会话更安全... - Eamon Nerbonne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接