asp.net cookie、身份验证和会话超时

Posted

技术标签:

【中文标题】asp.net cookie、身份验证和会话超时【英文标题】:asp.net cookies, authentication and session timeouts 【发布时间】:2010-10-02 01:29:09 【问题描述】:

我有一个使用表单身份验证的 asp.net 网站。我在会话中保留了一些内容,例如用户名、用户 ID、电子邮件等。

我允许用户通过在身份验证 cookie 上设置较长的过期日期来保持登录到网站。因此,会话在用户仍然通过身份验证时过期是很常见的。

我遇到的问题是有时用户的会话超时但他们仍然经过身份验证。因此,例如,我的一个用户页面(需要身份验证)在会话处于活动状态时会说“Welcome Mike”,但一旦过期,它会说“Welcome [blank]”,因为该信息不再在会话中,但他们仍然经过身份验证。

处理此问题的最佳方法是什么?当信息不再存在时,我应该重新同步会话信息吗?还是应该将用户信息(用户名、用户 ID、电子邮件)移动到 cookie 中,而不用担心会话超时?

我不想将会话长度设置为 60 分钟或更长。 我希望我的用户能够登录一次,而不必担心在他们明确退出之前必须再次登录。

【问题讨论】:

【参考方案1】:

尽可能避免使用会话,如果你可以在没有看见的情况下逃脱,它会使多服务器部署变得更容易一些。可能,姓名和电子邮件很容易成为 cookie 的候选者。伪造 cookie 很容易,因此根据您的安全需求,用户 ID 可能不是一个好主意。

表单身份验证 cookie 已加密,您可以向这些 cookie 添加额外数据(请参阅下面的详细信息)。它可能是可破解的,但不像简单的 cookie 那样容易。

这是我过去使用的代码,稍作修改以删除一些项目特定的细节。在登录控件的 LoggedIn 事件中调用它。

void AddUserIDToAuthCookie(string userID)  
  
  //There is no way to directly set the userdata portion of a FormAuthenticationTicket  
  //without re-writing the login portion of the Login control  
  //  
  //I find it easier to pull the cookie that the Login control inserted out  
  //and create a new cookie with the userdata set  

  HttpCookie authCookie = Response.Cookies[AUTH_COOKIE];
  if(authCookie == null)
  
    return;
  

  Response.Cookies.Remove(AUTH_COOKIE);

  FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(authCookie.Value);
  var newTicket =
    new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, oldTicket.IssueDate, oldTicket.Expiration,
                                  oldTicket.IsPersistent, userID, oldTicket.CookiePath);

  authCookie.Value = FormsAuthentication.Encrypt(newTicket);

  Response.Cookies.Add(authCookie);

仅供参考,我从一个旧项目中复制了它并在此处对其进行了编辑以删除一些项目特定的位,因此它可能无法编译,但它会非常接近。

要在您的网页中获取 ID...

FormsAuthenticationTicket ticket = ((FormsIdentity) Page.User.Identity).Ticket;
string id = ticket.UserData;

我使用这种机制来存储不属于 aspnetdb 用户数据的 id。如果您的所有身份数据都由 aspnetdb 处理,您可能只需要访问 Page.User.Identity 对象。

【讨论】:

是的,我很想知道如何向身份验证 cookie 添加详细信息。这可能正是我正在寻找的解决方案! 在我看来HttpCookie authCookie = Response.Cookies[AUTH_COOKIE]; 应该是Request.Cookies 我已经使用这个答案来帮助我的情况和我在研究时发现的其他人的问题 - ***.com/a/17961503/511438 在验证用户凭据后何时调用 AddUserIDToAuthCookie() ?为什么在将 cookie 传输到客户端之前将旧 cookie 数据放入新 cookie 中?【参考方案2】:

就我个人而言,我会保留 20 分钟的默认设置,并为您的网站添加“保持活跃”功能。制作一个简单的 javascript,每 5 分钟轮询一次,比如 heartbeat.aspx,以保持会话处于活动状态。这将扩展会话和身份验证,而不会保留疯狂的身份验证令牌。

有几个例子(我认为不好)如何做到这一点。我最终使用了基于AjaxLines's session timeout prevention 的东西。不过,我没有使用 ajax 库,而是直接使用了 xhtml 请求。没有什么比在心跳页面上对GET 的定时javascript 调用更需要的了。

【讨论】:

【参考方案3】:

从技术上讲,由于 asp.net 会话超时,您的用户不应被注销。这应该/由表单身份验证 cookie 控制。

所有与用户身份验证相关的基本信息都应保存在表单身份验证票的 USERDATA 属性中。此值不应作为会话保留在会话中。

仅将那些值保留在可重新创建的会话中。

因此,当您创建表单身份验证 cookie 时,您可以将所有基本信息作为票证的一部分传递。

--

您可以做的快速的事情是保持会话和表单身份验证的超时相同。这将是一个很好的做法。

会话超时会随着对站点的每个请求而自动延长。

而表单身份验证仅在 50% 的时间过去后才会延长其时间。

以下是有关此的详细信息: Forms Authentication FAQ

最简单的做法是在自定义 HttpModule 或基本页面中延长 Forms 身份验证时间,无论您的设计是什么。

通过这种方式,您的超时将始终保持同步,尽管可能会有一些细微的差距。

【讨论】:

【参考方案4】:

我自己没有实际尝试任何事情,有几件事我会检查一下。

使用允许您设置持久 cookie 的 FormsAuthentication 类的方法/重载。虽然,恕我直言,允许您的用户选择选中“记住我”框而不是强制他们持续登录是一种常见的礼貌。有许多方法可以让您根据您想要的行为来执行此操作 - SetAuthenticationCookie() 和 RedirectFromLoginPage() 是首先想到的。

查看 FormsAuthentication.GetAuthenticationCookie()。这将生成一个带有身份验证令牌的 HTTP cookie,但不会实际设置它,应该允许您更改您想要的内容 - 尽管如果 FormsAuthentication 模块正在寻找一个特定的值,可能会弄乱它打破认证。然后,您必须手动将 cookie 添加到响应中的 cookie 集合中。

【讨论】:

【参考方案5】:

我的首选方法是使用像缓存这样的会话。也就是说,尝试从 session 中读取,如果值存在则返回,如果不存在,则从持久存储(数据库等)中读取,放入 session 中并返回。

为了简化这一点,创建一个类,为会话中的每个变量添加一个属性,并在会话中存储该类的一个实例。然后创建一个静态方法来获取该类的一个实例。如果可以的话,我稍后会添加一个示例。

【讨论】:

以上是关于asp.net cookie、身份验证和会话超时的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET 窗体身份验证超时和会话超时

如何同步表单身份验证 cookie 和 Asp.Net 会话的生命周期?

根据 ASP.NET 中的角色设置身份验证 cookie 超时长度

MVC 身份验证超时/会话 cookie 删除后的 Ajax 请求

使用 WIF 和 jquery ajax 请求时 ASP.NET MVC 3 中的会话 Cookie 过期处理

ASP.NET 身份会话 cookie 的安全性如何?