views:

547

answers:

3

In ASP.NET, I'm looking for a way to audit a user leaving my application. To be specific, I'd like to insert a 'logout' record in an audit table in SQL Server when the user's session is abandoned/destroyed for any reason (not necessarily because of a call to session.abandon)

I have a 'SessionHelper' class that manages the session setters/getters.

I've tried posting back in Session_End in Global.asax, but it never fired this event even after the timeout expired.

I've tried overriding 'finalize' in the SessionHelper class and doing it there when the class is destroyed, but it did not fire that event either.

I'd try implementing IDisposable in the SessionHelper, but I don't know where to call it so that it always gets called.

What is the proper way to audit a user leaving your ASP.NET application?

Thank you!

+2  A: 

Note sure about the "proper way" but here's how I've done it in the past.

Have a "is active" date-Time stamp associated with the user record in the database. Everytime the user accesses a page, that is updated to the current time. If someone hasn't accessed the page in say 15 minutes, then that user is recorded as a "logout" event, and the timestamp is set to NULL.

Stephen Wrighton
I do something similar, i use sql based session handling and have a last accessed column in the table holding my session data. There is a stored proc that runs every time a session record is modified that cleans the tables of any unused session rows inactive longer than a predefined TIMEOUT value.
stephenbayer
+1  A: 

At best your logout record is going to be an intelligent guess, even if you do get the session events to work correctly, of when the user left your site/app. A technique you might use is to place the logout time into the db when the user logs in, and just keep updating the record with a future time as they use the system. Here is the general schema of a session table I used recently authored:

[Id]  [Uid]    [LoginInOn]        [ExpiresOn]  
 1    johndoe  10/14/2008 10:47   10/14/2008 11:07

In this table I just keep updating the ExpiresOn column as the user interacts with the application (current time + 20 minutes). If they try to interact after the ExpiresOn, then I know they were idle for 20 minutes and force a new login. For reporting purposes, I know the user has logged out if the current time is greater than ExpiresOn. You can get more complex than this. For example, I move my data out of the sessions table listed above to a reporting table with a regular process. This is just to keep the sessions table small, since a lot of stuff interacts with it.

Jason Jackson
+1  A: 

The Session_End event is only fired if you have InProc sessions. SQL or state server session management will not fire this event. If you can, get back to InProc sessions and use this event.

Apart from that, you won't get very good solutions. ASP.NET doesn't offer a way to look at the current list of sessions on the server (at least, no way that users of StackOverflow know of, since I already asked the question), so you can't use a job to check when they are destroyed.

The next best thing would be to have a "last access time" stored somewhere for your users and use that to detect a timeout of the session. The implementation of such a job is complicated though (you can miss logout events if a user logs in/out rapidly for example)...

So no perfect solution here.

Mathieu Garstecki