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

asp.net Cookie、身份验证和会话超时,asp.net,authentication,cookies,session,Asp.net,Authentication,Cookies,Session,我有一个使用表单身份验证的asp.net网站。我在会话中保留了一些东西,比如用户名、用户ID、电子邮件等 我允许用户通过在身份验证cookie上设置一个较长的过期日期来保持登录网站。因此,会话在用户仍然经过身份验证时过期是很常见的 我遇到的问题是,有时用户的会话超时,但它们仍然经过身份验证。例如,我的一个用户页面(需要身份验证)在会话处于活动状态时会说“Welcome Mike”,但一旦会话过期,它会说“Welcome[blank]”,因为该信息已不在会话中,但它们仍然经过身份验证 最好的处理方

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

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

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

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


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

尽可能避免使用会话,如果您可以不使用session就可以轻松地进行多服务器部署。可能,姓名和电子邮件是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对象。

而不必亲自尝试任何操作,有几件事我想检查一下

  • 使用FormsAuthentication类的方法/重载,该类允许您设置持久cookie。尽管如此,我认为允许用户选择勾选“记住我”框而不是强迫他们持续登录是一种常见的礼貌。有许多方法允许您根据所需的行为来执行此操作—首先想到的是SetAuthenticationCookie()和RedirectFromLoginPage()

  • 签出FormsAuthentication.GetAuthenticationCookie()。这将生成一个带有身份验证令牌的HTTP cookie,但不会实际设置它,这将允许您更改所需内容-尽管如果FormsAuthentication模块正在查找特定的值,干扰它可能会破坏身份验证。然后,您必须手动将cookie添加到响应中的cookies集合中


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


有几个例子(我认为很糟糕)说明了如何做到这一点。我最终使用了基于。不过,我没有使用ajax库,而是直接使用xhtml请求。除了对心跳页面上的
GET
进行一次定时javascript调用之外,实际上不需要任何东西。

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

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

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

因此,当您创建表单授权cookie时,您可以将所有基本信息作为票据的一部分进行传递

--

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

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

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

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

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


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

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


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

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