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

时间:2009-01-18 03:55:28

标签: asp.net authentication cookies session

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

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

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

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

我不想将会话长度设置为60分钟或更长时间。 我想要的是让我的用户能够登录一次而不用担心必须再次登录才能明确退出。

5 个答案:

答案 0 :(得分:18)

尽可能避免使用会话,如果你可以毫不费力地离开会使多服务器部署更容易。也许,姓名和电子邮件很容易成为cookie的候选者。伪造一个cookie很容易,因此根据您的安全需求,userID可能不是一个好主意。

表单身份验证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对象。

答案 1 :(得分:4)

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

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

答案 2 :(得分:2)

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

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

仅将这些值保留在可重新训练的会话中。

因此,当您创建表单认证cookie时,您可以将所有必要信息作为故障单的一部分传递。

-

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

会话超时会随着每个请求自动扩展到站点。

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

以下是详细信息: Forms Authentication FAQ

最简单的方法是在自定义HttpModule或基页中扩展Forms身份验证时间,无论您的设计是什么。

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

答案 3 :(得分:0)

如果没有亲自尝试任何东西,我会查看一些内容。

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

  • 查看FormsAuthentication.GetAuthenticationCookie()。这将生成带有身份验证令牌的HTTP cookie,但实际上没有设置它,应该允许您更改所需内容 - 尽管如果FormsAuthentication模块正在查找特定值,那么可能会搞乱它中断认证。然后,您必须手动将cookie添加到响应中的cookie集合中。

答案 4 :(得分:0)

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

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