表单身份验证超时与会话超时

66

我在我的asp.net网站中使用了以下配置的asp.net表单验证:

<authentication mode="Forms">
    <forms loginUrl="~/Pages/Common/Login.aspx"
           defaultUrl="~/Pages/index.aspx"
           protection="All"
           timeout="30"
           name="MyAuthCookie"
           path="/"
           requireSSL="false"
           cookieless="UseDeviceProfile"
           enableCrossAppRedirects="false" >
    </forms>
</authentication>

我有以下问题

  1. 如果我在表单身份验证中使用滑动过期,则会话的超时值应该是多少,因为会话将在表单身份验证之前过期。如何保护它?

  2. 在表单身份验证注销后,我想将页面重定向到logout.aspx,但它自动将我重定向到loginpage.aspx。这可能吗?

2个回答

56
  1. 为了保险起见: TimeOut(Session) <= TimeOut(FormsAuthentication) * 2
  2. 如果您想在身份验证超时后显示除loginUrl属性指定的页面之外的页面,则需要手动处理,因为ASP.NET不提供这样的方式。

要实现#2,您可以手动检查cookie及其AuthenticationTicket是否过期,并在它们过期时重定向到您的自定义页面。您可以在下列事件之一中进行操作:AcquireRequestStateAuthenticateRequest

事件中的示例代码如下:

// Retrieve AuthenticationCookie
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) return;
FormsAuthenticationTicket ticket = null;
try {
    ticket = FormsAuthentication.Decrypt(cookie.Value);
} catch (Exception decryptError) {
    // Handle properly
}
if (ticket == null) return; // Not authorised
if (ticket.Expiration > DateTime.Now) {
    Response.Redirect("SessionExpiredPage.aspx"); // Or do other stuff here
}

2
谢谢Dmitriy,我的第二个问题:如上所述,在<Form ...>内部,默认页面为“index.aspx”,登录为“login.aspx”。在我的仪表板页面登录后,当我保持30分钟不活动(超时),然后单击任何链接,我将自动重定向到登录页面,并显示以下URL http://localhost:/virtualdir/Pages/Login.aspx?ReturnUrl=%2fvirtualdir%2fPages%2fDashBoard.aspx但是在这里,我想重定向页面到注销页面,以便我可以说一些注销信息。 - Hemant Kothiyal
32
你确定希望将 Session.Timeout 设置为 FormsAuthentication.Timeout 的两倍以下吗?这意味着即使用户仍然登录,Session 也可能被放弃。任何引用 Session 变量的地方都会开始出现 NullReferenceExceptions。 - Dominic Zukiewicz
2
条件 ticket.Expiration > DateTime.Now 正确吗?我认为需要反过来,这样当当前日期时间大于表单身份验证票证过期时间时才会重定向。 - Daniel Ballinger
4
同意Dominic的观点。在清除会话时保留表单认证具有有效目的(这可能是大多数应用程序想要采用的方式)。然而,我有一个(安全的移动Web)应用程序,我希望恰好相反,并使用频繁的表单认证作为身份验证方式。我希望这个答案包括支持您建议的过期模型的理由或示例。 - Jason
8
我对让表单身份验证的过期时间比会话后过期还要晚感到困惑。这对我来说没有意义,但这里有一篇支持此观点的博客文章。另外,还有一个微软开发者网络的文章链接,试图加强这个解决方案。 http://itworksonmymachine.wordpress.com/2008/07/17/forms-authentication-timeout-vs-session-timeout/ http://support.microsoft.com/kb/910439 - MADCookie
显示剩余6条评论

28

对于有会话依赖的网站,您可以在global.asax中使用session start事件简单地注销过时的身份验证:

void Session_Start(object sender, EventArgs e)
{
  if (HttpContext.Current.Request.IsAuthenticated)
  {

    //old authentication, kill it
    FormsAuthentication.SignOut();
    //or use Response.Redirect to go to a different page
    FormsAuthentication.RedirectToLoginPage("Session=Expired");
    HttpContext.Current.Response.End();
  }

}
这样做的结果是,新会话等于新的身份验证,没有例外。

1
它似乎有些强制性,但在目前必须进行会话的情况下,这对我们来说是一个不错的选择。 - Alex KeySmith
3
我不确定我会称它为"forceful"。它只是将会话认证状态结合在一起。当然,更强大的选择是根据身份验证令牌来恢复会话。但如果会话恢复是事后考虑的(即分散在各个地方),最简单的解决方案是让用户回到已知路径(登录)。 - b_levitt
没错,这是我们采取的路线,直到我们能够让会话在运行时重新创建。 - Alex KeySmith

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