如果会话已过期并且用户单击指向另一个webform的链接,则asp.net身份验证会自动将用户重定向到登录页面。
但是,有时用户没有点击指向其他网络表单的链接。例如:在gridviews中编辑链接,当使用带有文本框的AutoCompleteExtender并且应用程序尝试获取信息时,基本上,在每种情况下,当回发完成并且事件不是由asp.net身份验证自动处理时。
处理这些例外的最佳方法是什么?
更新:我刚修改了问题标题:表单身份验证超时,而不是初始会话超时。感谢您让我意识到这种差异。
更新:我刚刚针对我面临的具体问题创建了一个新问题:How to handle exception due to expired authentication ticket using UpdatePanel?。令人惊讶的是,我没有找到关于它的更多信息。我非常感谢你的帮助。
答案 0 :(得分:10)
这就是为什么许多系统在页面上包含计时器以提供大致的超时时间。交互式页面很难实现。你真的需要挂钩ajax函数并查看返回状态代码,这有点困难。 一种替代方法是使用基于以下内容的代码,该代码在页面生命周期的早期运行并执行ajax重定向到登录页面。否则你会试图拦截来自ajax和asp.net的返回代码,其中ajax是为你做的(即不是像jQuery这样的更手动的方法)你会失去这种易于检测。
快速入侵你可以直接在pre_init中试试 http://forums.asp.net/t/1193501.aspx
修改强> 需要的是表单身份验证超时,而不是会话超时。表单身份验证超时的运行时间与会话超时不同。会话超时随每个请求更新。表格身份验证票据实际上没有更新,直到有一半的时间流逝。因此,如果您将超时设置为一小时并在一个请求中发送25分钟,则会话将重置为一小时超时,表单身份验证票未触及并在35分钟后到期!要解决此问题,请同步会话超时和表单身份验证票证。这样您仍然可以只检查会话超时。如果您不喜欢这样,那么仍然 - 执行以下操作并同步超时,然后解析身份验证票并读取其超时。您可以使用FormsAuthentication.Decrypt执行此操作 - 请参阅:
Read form authentication cookie from asp.net code behind
请注意,此代码需要在登录时设置一些会话值 - 在本例中为“UniqueUserId”。同时更改下面的登录页面路径以适合您的。
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
//Only access session state if it is available
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
//If we are authenticated AND we dont have a session here.. redirect to login page.
HttpCookie authenticationCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authenticationCookie != null)
{
FormsAuthenticationTicket authenticationTicket = FormsAuthentication.Decrypt(authenticationCookie.Value);
if (!authenticationTicket.Expired)
{
if (Session["UniqueUserId"] == null)
{
//This means for some reason the session expired before the authentication ticket. Force a login.
FormsAuthentication.SignOut();
Response.Redirect("Login.aspx", true);
return;
}
}
}
}
}
答案 1 :(得分:1)
如果您正在使用表单身份验证,则表单身份验证票证到期时,用户将被重定向到登录页面,这与会话到期时不同。
如果合适,您可以考虑增加表单身份验证超时。甚至到使用持久性cookie的程度。但如果它到期,那么重定向到登录页面没有其他替代方法 - 其他任何东西都是不安全的。
处理会话超时的一种方法是使用Session作为缓存 - 并保留对后备存储(如数据库)重要的任何内容。然后在访问Session中的任何内容之前进行检查,并在必要时进行刷新:
MyType MyObject
{
get
{
MyType myObject = Session["MySessionKey"] as MyType
if (myObject == null)
{
myObject = ... get data from a backing store
Session["MySessionKey"] = myObject;
}
return myObject;
}
set
{
Session["MySessionKey"] = value;
... and persist it to backing store if appropriate
}
}
答案 2 :(得分:0)
如果您正在使用母版页或基页,我会在页面生命周期中的一个事件中添加一些逻辑来检查会话是否是新的:
protected void Page_Load(object sender, EventArgs e)
{
if (Session.IsNewSession)
{
//do whatever you need to do
}
}