chiname

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::
? 要说到session这个东西,很多人可能都不屑一顾。这个东东嘛,n年前就开始做了,有
啥好讲的啊。可是,在很多地方我们还是会发现一些问题,比如有的人说,我的
session_start激发了,怎么session_end没有啊,我在session_end做了些善后工作,
这下没法完成了,怎么办啊?

? 最近看了些文章,结合自己的一些经验,想和大家一起讨论一下其中的说法。

? 其实,很多这类的问题都是由一个东西引起的,它就是session ID。首先,是不是我
一个IE client起来,访问一个页面,只要我不关浏览器,session ID就是一样的呢?
很多人会想,应该是一样的吧,我浏览器都没关,web server总归会认为我是同一个
client,不会把session ID变来变去的。要验证这个,让我们现在做一个简单的试验。
用vs.net创建一个简单的asp.net web app.在web form1上加个button,然后在页面的
page prefix上enable trace.接下来浏览这个页面,不停的click button来提交
request。感谢asp.net的这个trace功能,我们可以看到session ID其实是在不停的变
化的。也就是说,这时候在服务器端,根本就不关心这个client的存在,每次都觉得它
是来自一个新的client.

? 那这到底是怎么回事呢?OK,让我们在page_load里面加上一句,
session["variable1"]="testvalue";然后再做一下测试。Bingo,现在session ID就保
持一致了。我想,很多人也许以前就没有注意到这点。这里我们可以得出一个结论:要
建立一个持续的session,咱们需要至少使用一下session变量,用行话来说,就是要至
少往session dictionary中写入一次。

? 不过,值得注意的是,这只是个必要条件,还不是充分条件。

? 在提到下一个必要条件前,我们先来弄清一件事,如果我们在程序中间有
global.asax,里面有session_onstart, session_onend,上面的实验是不会成功的。原
因是一旦定义了session_onstart处理函数后,session的state就总是会被保存了,即使
里面是空的,这样的话,session ID就不会改变了。因为session这东西还是消耗资源
的,所以在asp.net web app中如果没有必要,你就不要把session_onstart,
session_end写在global.asax中。

? 上面的实验中,我们也可以看到,如果session ID在变化,我们就跟踪不到
session_onend,一旦稳定下来,session_onend就出现了。

? 现在,我们再来谈谈另一个条件,还是先从实验做起,我们在刚才例子的基础上(包
括session_onstart, session_onend),在page_load的session那行的下面加上一句,
session.abandon().再来运行一把,咦,这是你会发现一点奇怪的地方,session_onend不
执行了,尽管session_onstart执行过了一遍。(这里我们需要写一些log语句来观察
到)而且,如果我们把session.abandon()写在button.onclick事件里面,
session_onend就立马执行了。奇怪吧,这里有什么区别呢?

? 这样,第二个必要条件就引发了,要让session_onend成功执行,至少要有一个
request已经被完整地执行过。上面的第一种情况,在page_load中就中止的话,第一个
request都没有执行完毕,session_onend就没法激发了。

? 综合这两个必要条件,我们终于可以得出要让session_onend执行的充分条件了:
? 1)至少有一个request成功完整地执行
? 2)至少存储一些data在session state中。可以通过session变量或者加上
session_onstart来实现。

? 最后声明一点,session_onend只在InProc模式中支持,也就是说,只在session
data在asp.net worker process中时支持。


Q I'm using forms authentication, and when the user's session times out, he is sent back to the login.aspx page. At that point, if the user reenters his login information, he is taken back via FormsAuthentication.RedirectFromLoginPage to the page he was last viewing. How can I put a message on the login page to tell them that their session has timed out and they must log in again?


A Two distinct concepts are actually at play here: session state and forms authentication. When using in-process session state, Session_End does not map to your forms authentication session timing out. Session_End will fire silently on the server side x minutes after the last request to an ASPX page in the application (x being the session state timeout). Based on the description you've provided, what seems to be happening is that the authentication ticket embedded within the forms authentication cookie is expiring. Once that happens, the user will be redirected to the login page, but Session_End will not fire.

You really can't do a Response.Redirect or similar command in Session_End for the simple reason that this happens totally on the server side (without any HttpContext, since no request really caused the session to end).

If you're using in-memory nonpersistent cookies, you could try using something like this in Page_Load of your Login.aspx.cs file:

if(Request.Cookies["SyprosCom"]!=null)
{
    Response.Write("Redirected due to forms. Auth. timeout");
}

However, this logic will fail if you are using persistent cookies and the cookie timeout is equal to the forms authentication ticket timeout. For more information on ASP.NET session state take a look at Understanding session state modes + FAQ, ASP.NET Session State, and Using ASP.NET Session State in a Web Service.


Q: I have set the timeout attribute in my web.config file to
1. I have set a breakpoint in VS.NET on the Session_End
event handler in the Global.asax file and am running the
web app in debug mode. I have also opened the System
Monitor and am looking at the Sessions Total, Sessions
Active and Sessions Timed Out performance counters.

When I run the web app in debug mode, I notice that the
counters for Sessions Active and Sessions Timed Out change
when the session times out. However, since I am running it
in Debug mode with a break point set on the Session_End
event, I debugger does not stop at the breakpoint. Its as
if the event does not get fired at all.

Shouldn't the Session_End event get fired when the session
times out? I noticed that there are no event handlers
(like this.Load += new System.EventHandler
(this.Page_Load)) in the InitializeComponent method call.

I dont know where to go from here. Any help is
appreciated.

A: Keep in mind that there are some circumstances in which this event might not
fire:

* If the session is terminated manually (for instance you click the stop
button in Visual Studio.)
* If you are not using the standard in proc sessions (i.e. you're using SQL
Server to store state.)

I believe there are a few other obscure things that could prevent it from
firing too, so take this into account when designing your solution by having
some kind of cleanup routine to handle any sessions that slip through the
cracks.
Here's more info:
http://www.asp.net/Forums/ShowPost.aspx?tabindex=1&PostID=7504
posted on 2005-01-11 16:44  把我的欢乐带给你  阅读(963)  评论(0)    收藏  举报