Can you advise me on how to kill somebody's session and make them logout from my MVC app.
My current plan is:
On the start of the app to load a SessionsCache
When user logins - save his session in tblSessions and partially reload the cache (add the session in it without making it call the DB)
Every 30 seconds an ajax will validate whether I have session or not
The administrator will have an interface tool containing all active sessions in the cache and when he kills a session he deletes it from the cache and DB
On the next ajax call the user wont have session and would be logouted
If a user logouts normally the session in the cache and DB will be deleted
Every 30minutes a full reload on the cache would be done
Please consider that my application has OnActionExecuting() overriden function which checks if the user has session and if not loggouts him.
But this happens only on action execution and if the user doesnt click anywhere (afk) he wouldn't be redirected to home page. (considering maybe the ajax call to check session is redundant?)
Also i want to clear user session when he closes the browser/tab without using the LogOut button but I am not sure how can this happen
There's a few issues with your proposed solution that makes it unworkable:
Both sessions and auth employ client-side cookies to manage their status. The server can only invalidate the authentication/session. It cannot actually "log out" a user directly, because that piece is not under direct server-control. In other words, you can set up something that says that a particular user should be logged out, but that user will not actually be logged out until they attempt to make another request and some check is performed by the server which then affects that status change on the user at that time.
Sessions employ sliding timeouts. That means any request the client makes will reset the timeout of their session. In other words, if you long-poll the session status every 30 seconds, the user will effectively have a perpetual session that will never ever expire.
Sessions are intentionally anonymized. For security reasons, the client's only link to their session is the cookie with their session id. This prevents a certain level of session hijacking by making the cookie a must-have component in a successful attack. With things like the Secure token, then, and of course utilizing SSL on your site, you can effectively prevent that cookie from being usable in any other context than the client it was assigned to. The long and short is that there's not really any way to figure out which session belongs to a given user outside of direct contact with that user.
Cache is by nature volatile. You can say that particular key should have a lifetime of some period, but that's merely a suggestion. There's any number of different factors that could cause a cached item to be destroyed, most completely outside of your control.
Given all that that, you must approach this from a different direction. My suggestion would be to have a separate table where you track logins/sessions, in a generic sense. It would basically be a kind of log. When a user logs in or creates a new session, you would add a record to this database. If the user's auth or session expires, you would update the appropriate record. If the user deliberately logs out, you'd delete the record or otherwise mark it as inactive. As far as your admins go, they would then manage this table, removing or marking records as inactive.
Then, you will have to add some logic around your site actions to account for this table. You could create an action filter that checks this table and performs any necessary operations. For example, if the user has been "signed out" by an admin, the action filter would read the appropriate record from this table, see that the user had been signed out, and then affect that change by actually signing the user out.
Since long-polling will cause the session to never expire, you would essentially need to manage your own timeout. For example, you could record the time the session was created in the "log" table, and then compare that time with the current time on each subsequent request (including AJAX). Again, you could employ an action filter for this purpose. If the session is "expired" based on your timeout, then you could manually destroy the user's session.
There's plenty of other things you'd need to add or account for in this way, but hopefully that gives you a good framework to work from.
Related
I am using the Session object in my code to store the user login which will be saved to the DB.
I want to make sure about the the behavior on session timeout.
If the session times out what can the user do? I guess browsing to different pages does not restore the session? so only choice is to Close all of the browsers and come back in and Session gets alive?
I want to know under what conditions Session won't be alive again.
Also does Session time out fires the Session_End in the global.aspx?
A session is considered active as long as requests continue to be made
with the same SessionID value. If the time between requests for a
particular session exceeds the specified time-out value in minutes,
the session is considered expired. Reference
I believe that you are checking if the user is logged in or not in each page (or in masterpage), so as long as the user is not idle and he is using the system, the session will be updated and no worries.
If the user was idle for a long time and the session was expired, then it is logical to make him sign in again for security reasons.
use this on logout:
Session.Remove("sessionname");
I believe you're not explicitly killing the session by calling Abandon method on the session object in Session_End event.
Logging out of session makes this event to fire.And obviosly the user must be brought to the login page while trying to naviagte between pages.
Using the session to store a validated user's details is quite common. The session times out after a period of inactivity (I believe it's 20 minutes by default but can be changed in web.config.) This is usually desirable because if the user abandons the site (or walks away from their computer) without logging out it will kill (eventually) the session and effectively log them out automatically.
Reading or writing to the session will reset the timeout countdown. So if each web page check to see if the user is logged in all they will need to do if view a new page within 20 minutes and they won't be logged out.
If the user logs out (or the session times out) they don't need to close their browser, just go back to the login page and login again. So for each page that should be protected, check if their session exists and is logged in or else redirect them to the login page.
Yes the session timing out fires the session_end event.
I've got an application that's using the MVC4 Simple Membership provider. I've added some code to the Login method that sets up some session information I need to deal with some security things.
If I close the browser and come back to it, MVC still shows me logged in in the top left corner and the User.Username properties are still filled out, but the extra stuff I put in there, obviously, isn't.
When or where does this "authentication" take place? I tried checking the request and user objects in the Application_Start in Global.asax, but they're still null when that runs.
Is there somewhere else in that authentication pipeline that I can override or call my method to extract the things I need that would be more appropriate?
Thanks!
"Remember me" functionality has nothing to do with Simple Membership, or any membership. And no actual "login" occurs when using it. It's a persistent cookie that is placed on the users system, and that cookie is read when a page is loaded. If it contains the correctly encrypted data, then the user is considered authenticated without having to go through Membership validation again.
What you need to do depends on how you are doing it. If you're storing data in the session, this is bad regardless, because the session can be reset at any time, and session is not connected to authentication. What you need to do, is check to see if the data you need is in the session, and if not, rebuild it. This way it works when you come back later, or if your session is reset.
Session probably shouldn't be used anyways, because it doesn't scale well. A better choice would be to hook into the OnAuthorization method of the Controller class and do what you need there, that way it's done on every page request regardless of what the session may or may not be.
Another option is to create a custom AuthorizationFilter.
Is it possible to allow only one concurrent login per user in ASP.NET web application?
I am working on a web application in which I want to make sure that the website allows only one login per user at a time. How to check that the current user already logged in or not?
Please suggest proper login method by which we can handle this problem. I think we should use SQL Server session state to handle this problem. What do you suggest?
I thought of one solution for it. We can do something like:
When the user logs into the system then we insert session id in user column. (We will use database session so that we can get all session related data like isexpired, expiredatetime etc easily).
When the same user tries to login a second time then we will check for that session id column and check that session is already expired or not. If session is not expired then we will not allow user to login.
Update user session ID every time when user logs out.
Please suggest whether this is the proper way or not.
Please refer to:
When the same user ID is trying to log in on multiple devices, how do I kill the session on the other device?
Out of the box, .NET does not support this. .NET allows for concurrent log-ins, as I'm sure you're aware.
I had this same exact requirement, and came up with a pretty slick solution, demonstrated in the link above. In a nutshell, my requirement was to only have one user log-in happening at one time. If that same user ID tried to log in elsewhere, then it killed the session for the first log-in by checking for an existing log-in under a different Session ID (this enabled the user ID to be logged in from multiple instances of their web browser on their computer [same Session ID], which is common, but not from a different computer [different Session ID] (possibly due to someone that stole their credentials, for example)). Through modification of the code you could probably change the behavior of this - i.e., prevent the second log-in attempt instead of killing the first log-in that's already active and in use.
Of course, it may not fit 100% to what you're needing, so feel free to modify it to fit your needs.
You can create a cache entry per user and store their session ID in it. Session ID will be unique per browser session. In your login page, you can create that cache entry when they successfully login:
if(Cache.ContainsKey["Login_" + username])
// Handle "Another session exists" case here
else
Cache.Add("Login_" + username, this.Session.SessionID);
(Code typed in textbox without syntax check. Assume "pseudo-code".)
In global.asax you can then hook into the Session_End and expire that cache entry of the user. See this for the global.asax events.
if(Cache.ContainsKey["Login_" + username])
Cache.Remove("Login_" + username);
You could add a flag column in the user table that indicates that a user is currently logged in.
When a users attempts to log in you check the flag if it's true (that users account is already currently used) then you don't allow the new user to log in, if the flag is false the users is allowed to log in as there account is not being used by anyone else at this time.
Be aware though that unless the uses actively logs out, you cannot know when the users moves on to something else (goes to different website or closes the browser, etc.) so you need to set some kind of session timeout that will automatically log out the user if there are no new requests within a specified time period.
This means that if a users closes his/her browser and try to log in on a mobile device for example, he/she will be unable to log in until your specified session timeout runs out, so give the timeout a bit of thought as you don't want the user to get logged out to quickly (if he/she is reading a long page, etc.) and you don't want the users to be unable to log in on another device for hours if he/she forgot to log out before leaving the home.
The login credentials are stored on the cookie, so to know if the user is logged in you need to keep this informations on server, prefered on a database because the database can be the only common place among web garden or web farm.
What you can keep, is on a table, that the user A is logged in or not, flag it that is logged out, maybe last user interaction to have a timeout, etc...
So let say that the User A, is logged in, then you open a flag on the database for that user, that is now logged in, and if is try to logged again, you keep him out.
To make this work you need to either say to your users to log out, or to keep a time out, similar to the time out of the credentials.
If You are using identity system this link will help you how to single user login on multiple device.
Prevent Multiple Logins in Asp.Net Identity
I have tried they work fine in my Asp.net Mvc Project.
Solution can be this way:
Add new column in your login table GuidCode.
Step 1 : When logging in check if the GuidCode in database is null.
Step 2 : Update GuidCode by new guid and also store it in the session.
Step 3 : If it is not null then take guid from the session and compare with database GuidCode value.
Step 4 : If it is same then allow login:
i want to create a global session which will stay active until and unless we manually kill it. how to do this in asp.net with c#
what i am doing is
HttpContext.Current.Session["UserID"] = someValue;
but in this way the session is lost after some time.
You can set the timeout in web.config under system.web -> sessionState -> timeout. Not sure if you can have an infinite session though.
Also, you might be interested in the Application object which stores things in the "application's session" instead of the user's. Comes to my mind because you speak of a "global" session.
What's the application for this? Sounds like you're actually trying to use the session as a persistent storage, which will however only seemingly work even if you manage to set timeout to never or 5 years or whatever - because sessions will be "timed out" once the application is restarted. You might still get around that, but you might be better off looking for real persistence solution like a database. I may be totally off guessing your application for that of course.
Store the data in the Application state rather. It will stay there till you remove it, or the app dies/recycles/ends.
Usage:
HttpContext.Current.Application["Foo"] = "bar";
As nicolas78 says use session timeout configuration property to control the session expiry after user inactivity. In case, you are facing a requirement where session should be active as long as browser is open, there are two ways -
Use cookie to store some token and then re-construct your session state using the token if session gets expired. For example, user details can be recovered from user store if user id is stored in token. At worst, you may have to move your entire state to the database.
Keep the ASP.NET session state but keep it alive by firing AJAX requests from browser. I would suggest to fire such request after n/3 interval where n is your session timeout (ensuring at least three requests are made so even if two gets lost or falls on edges, one gets through).
Perhaps you're after profiles?
http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
Profiles live beyond the session and are usually used to store per-user settings that the user can edit, such as their contact details and application preferences.
Profiles can be used with both anonymous and authenticated users. When an anonymous user signs in, their anonymous profile can be migrated into an authenticated profile (i.e. one that is attached to their user name).
Good walkthrough here: http://quickstarts.asp.net/quickstartv20/aspnet/doc/profile/default.aspx
I have an ASP.NET MVC application running on IIS7. I use sessions to keep track of logged in users. There is a session named IsSignedIn. ("true" means this user is currently logged in).
I also have an administration page for my application.
Now, say user1 who is signed in already, must be suspended from using the service immediately. So I want to invalidate the session variables set for user1 from my administration page (this will force the user to sign in again).
Is there a way I can access/modify session variables set by each logged in user from my administration page?
You can not change a session variable from another session.
One way to solve your problem is to store a list of logged in users in the Application-object, and then change the value in that variable. For this to work you must check at the top of each page that this user is in the list of logged in users.
As çağdaş commented on this answer, performance would probably be better if you store a list of users you want to log out in your application-variable. Then on the top of your page do something like this (pseudo, this actuall code snippet will not work)
if(Application["SuspendedUsers"].Contains(Session["UserID"]) {
Session["IsSignedIn"] = false;
Application["SuspendedUsers"].Remove(Session["UserID"]);
}
Where is your session state stored? If it's in SQL server, you should be able to invalidate it by updating the relevant row in the database. The standard session state server, however, doesn't appear to allow this.
Alternatively, check your database at the top of each relevant page to see if the user still has rights/is authenticated.