accessing another user's session state

  • Thread starter Thread starter Andy Fish
  • Start date Start date
A

Andy Fish

Hi,

In my asp.net 2.0 application (which uses internal session state), I
wanted to put in a screen so that the system administrator could see
who was logged on and kick users off by killing their session if they
wanted.

By putting all the session objects into a global cache, I found out I
am able to access session variables from other sessions with no
problem. However, calling Session.Abandon() on any session other than
the current one doesn't seem to have any effect - the Session_End
event in global.asax is never triggered and the user can continue to
work as normal.

On closer inspection, it seems that each page request creates a new
HttpSessionState object but that all the HttpSessionState objects for
the same session (i.e. with the same session id) share the same
container of session state objects. calling Abandon on a session,
simply sets the Abandoned flag to true for that session object (i.e.
not for other session objects with the same session id).

Any thoughts of a good way to implement the ability to kill another
session? At the moment I'm thinking that I need to have another global
variable (or session variable) that gets switched by the 'kill'
feature and then at the top of each page I will check whether the
session has been killed by the administrator.

Andy
 
Ouch! Really...?


Under no circumstances do this!!! Session is specifically designed *NOT* to
be global...

the original reason for having a global session store is this: we have
a use case where a user views a PDF from the web app using acrobat on
their pc, and an acrobat plugin which we have written needs to use a
web service to get details from the user's session independently of
the browser. the cleanest solution seemed to be allow access to the
web session from the web service (obviously using a security token to
protect access)

That's right. Session.Abandon() works on your session only - it can't work
on other sessions...


Thankfully, that is absolutely correct!


I would strongly advise you not to even try. The Session object is designed
specifically not to be accessible externally.


Forget about using Session for this - it's not designed to work this way.

I don't see what the problem with using session is - i've just
implemented it and it seems to work fine. Bear in mind that my
application only works with inproc session state.
You could do something similar by setting a flag in a database table -
however, there are problems with this:

1) This will fall to pieces if your users don't log out "properly" i.e. if
they just close their browser or navigate away from your site rather than
clicking the Log Out button (or however you've designed it). A common
misconception is that such an action will cause Session_End to fire - it
won't! If a user simply closes their browser,

in my experience, the session_end always fires after the session
timeout has expired
the database flag will not be
reset and therefore the administrator will think they're still logged in.
More importantly, if the user tries to log in again before their Session has
ended naturally (normally after 20 minutes), the system itself will think
they're still logged in...

this is not a problem in my scenario because as part of the process of
forcing them off, I remove their session variables. when the page
detects they don't have the correct session variables it abandons the
session and requires them to log in again
2) Administrators "playing God" by kicking people off sites *really*
infuriate users... Why do you think you need to do this anyway, AAMOI? Isit
a licensing issue...?

the system connects to a document management system in the background
and the connection is too expensive to keep re-establishing so it's
stored in the session and relinquished when the session ends. there
are a numer of cases where it might be useful to close close this down
and tidy up the resources associated with it, for licensing and/or
other reasons.

 
Yes it does - I said as much.

But a user closing their browser or navigating away from a site *doesn't*
cause Session_End to fire because the server knows nothing about it...



You're missing the point. If a user closes their browser or navigates away
from your site without logging out, you won't know about it - how could
you...?

OK I think we're basically agreeing with each other. If the user
closes the window I do get to find out about it but only 20 minutes
later when the session_End event fires. If the user tries to access
the system in the intervening 20 minutes, regardless of whether their
browser thinks they are logged in or not, I will redirect them to the
login page because their session has been killed
 
How has their session been killed? It hasn't timed out yet...

well, if the sysadmin has "killed" their session, it will be in the
killed session list so the app will know it's been killed and will
abandon it properly before taking them to the login page

if it hasn't been killed by the sysadmin, it's still there and they
are still loged on
 
Andy Fish said:
the original reason for having a global session store is this: we have
a use case where a user views a PDF from the web app using acrobat on
their pc, and an acrobat plugin which we have written needs to use a
web service to get details from the user's session independently of
the browser. the cleanest solution seemed to be allow access to the
web session from the web service (obviously using a security token to
protect access)

Just to re-iterate (since this thread seems to lost this point later on)
this is not a good thing to do. Session objects are not thread-safe so by
placing them accessible globally you are running some unknown risks. You
also are changing the generally expected life-cycle for the session object
which my also result in some unexpected behaviour. The fact that is "seems"
to work fine now doesn't mean that it won't give you problems in the future.

Its worth bearing in mind that from time to time strange stuff happens or
goes wrong and needs investigating. Having unusual practices in the site
creates an area of uncertainty which could distract you from finding the
real problem. There is always the question "I wonder if those sessions
stored in cache has caused this or that?" in the back of your mind while
investigating something totally unrelated.

Is your acrobat plugin not forwarding the session cookie when making its
requests? I'm not quite sure why the "web service" needs the session placed
globally, why is it not in the request context?
 
[WebMethod( EnableSession = true )]

....


"the original reason for having a global session store is this: we have
a use case where a user views a PDF from the web app using acrobat on
their pc, and an acrobat plugin which we have written needs to use a
web service to get details from the user's session independently of
the browser. the cleanest solution seemed to be allow access to the
web session from the web service (obviously using a security token to
protect access)"
 
You could do something similar by setting a flag in a database table -
however, there are problems with this:

1) This will fall to pieces if your users don't log out "properly" i.e. if
they just close their browser or navigate away from your site rather than
clicking the Log Out button (or however you've designed it). A common
misconception is that such an action will cause Session_End to fire - it
won't! If a user simply closes their browser, the database flag will not be
reset and therefore the administrator will think they're still logged in.
More importantly, if the user tries to log in again before their Session has
ended naturally (normally after 20 minutes), the system itself will think
they're still logged in...

Maybe I'm missing something, but if the goal is to see if the user is
logged in, you wouldn't need to see if the user ever logged out or if
the user's session timed out. So in the DB, once the user is logged
in, set the "LoggedIn" flag to true. On each page refresh, check the
status of that flag... If the admin wants to kick the user off, set
the "LoggedIn" flag to False.... on the fresh, if the status=false,
redirect the user to the login screen with a message, or some other
nice way to say "Get the F*** Out"!!

So let's say you had a session var of UserID which contained the
UserID of a user who was authenticated for the current session. The
app would check to make sure that UserID is set AND the Flag=True.
 
Back
Top