views:

411

answers:

4

I'm basically looking for the event that is the opposite of FormsAuthentication_OnAuthenticate. I want to remove some values from the database when a user logs out. I tried putting it into the Session_End event, but it seems that the user is already gone by the time this executes.

Update: If I can't determine when a specific user is deauthenticated (ie, due to session timeout) then is there a way to get a list of all currently authenticated users? If I could, then in the Session_End I could just remove the records from the DB that are not associated with a currently authenticated users.

A: 

I would imagine you have them logging out via the click of a button or link or something like that. Why not just put the code in that same event / block. Near where you put the FormsAuthentication.SignOut() call.

NYSystemsAnalyst
A: 

There is a Session_End handler in the Global.asax in which you could put could that you want to execute when the session expires.

I am not sure that this is what you want though. Session and authentication are two different things. If your authentication technique is providing a FormsAuthenticationTicket to the user (inside a cookie) and that ticket has an expiration, well the expiration of the authentication is controlled via this ticket. It will not be actively managed on the server. Each request the user makes the ticket is provided and the server then determines if the user is still authenticated.

Bottom line is, you can detect when the user's session expires, but you probably won't be able to determine when their authentication expires, unless both expiration values are identical.

Jim Petkus
A: 

If you're using the SQL provider, the aspnet_Users table has a "LastActivityDate" column. If you compare that to the timeout value of forms authentication, you could come up with a list of users are definitely not logged in. Your count would be low if they log out manually with a "log out" link.

Greg
+1  A: 

Session_End isn't guarenteed to fire - if you're not using InProc sessions for example, then it won't fire at all. If your application recycles or dies, again, it won't fire.

Your best bet would be to have this code in a shared method that you can call from numerous places:

  1. In your LoginStatus control you can set the LoggingOut event - call your method there to handle people who log out sensibly.
  2. If you're using InProc sessions, in your Session_End event, but make sure you check to see if they are logged out already (as you've seen).
  3. If you're not using InProc sessions, you'll need to get a little more creative. Perhaps look at having an event that fires every now and then (perhaps on Session_Start which does fire regardless) that goes through and clears out those users who's last active time is older than the session timeout (as mentioned by Greg).

Unforunately the Membership class gives you some useful details, but not all of them:

GetNumberOfUsersOnline

This will "Gets the number of users currently accessing an application." - great, but the only methods that will get users either:

GetAllUsers      // Gets all the users from the storage provider (can be paged)
FindUsersByName
FindUsersByEmail

Sadly none of these have a property to only return "active users" as per the count.

Looking at the members of MembershipUser there isn't a "IsOnline" property - only LastLogonDate and LastActivtyDate - due to the disconnected nature of the web, this is probably as good as you're going to get.

Zhaph - Ben Duguid