ASP.NET MVC Object locking mechanism - asp.net-mvc

I'm working on a ASP.NET MVC 2 web application that lets users edit parameters on a simulation and launch it. Once a user starts editing a specific simulation, it must be inaccessible to other users.
Is there an easy way to achieve that goal in ASP.NET MVC?
My first idea was to put the logged on user's identity in the Application collection, along with the simulation:
Application.Add((Guid)Membership.GetUser().ProviderUserKey, simulationId);
Then I would remove it in the Session_End method, when the session expires. However, the Session_End method is never called with those parameters in the web.config file:
sessionState mode="InProc" timeout="1"
What am I doing wrong? / Is there a better mechanism?

Hard to do in a web application. Can you tell us why? usually collision detection is used in this instance and the first updater wins. The second updaters can either be told "refresh your data and retry" or you can try to apply or merge the changes and offer to save the newer version.

Related

Why am I getting a new session when using async actions and RedirectToAction in ASP.NET MVC?

I have an ASP.NET MVC 4 application that is exhibiting session management problems.
I'm using the Session to track the logged in user. I have a custom action filter that checks a user is logged in and, if not, redirects to the log in page.
This generally works fine. However, I have a problem where a new session is getting created during a certain request. The session ID is the same, but the Session.IsNewSession property shows it's a new session - and the session contents have gone.
The action where is happens is an async action (using the async/await features in .NET 4.5). I don't manipulate the session in the thread that is invoked with the await keyword. When the await operation completes, I then do a RedirectToAction to display the results of the operation.
When I check the session, just before executing the action I've redirected it to - it has the custom access attribute on it - that's when I find a new session has been created (so the authentication fails and I'm return to the login page).
I use RedirectToAction at numerous points in the application, so that can't be the issue (or at least the only issue). Could the problem be something to do with the async/await call - even though I don't use or need the session within the code that is invoked by the await?
Is returning the ASP.NET thread to the pool and getting it back invalidating the session? If so, what's the solution? Can I save and restore the session across the await? Or will I have to implement some custom logic that records that the user was logged in in my database, for example?
Turns out that the problem was being caused by a Win32 DLL I'm using that was "touching" (i.e. changing the timestamp on) a config file. This was causing the web app to be reloaded at that point - thus invalidating the session.
I got this behavior when the green arrow at the top of Visual Studio Professional 2017 was set to "IIS Express". When I changed it to "IIS Express (Google Chrome)" my session variables quit disappearing every time I called RedirectToAction. I read in one of the posts that it could be related to the browser cookies.

ASP.NET MVC: A PreAuthorize-like event, Good throttle point for concurrent logons?

I want to allow a new login to 'kick' a prior login session by the same account, in ASP.NET MVC.
It seems pretty clear that I'll give each browser a cooking representing the session ID. I'll track the currently active session ID in a server-side cache. If an already-active user attempts to log in, I'll verify the business logic (username, password, has been at least 15 minutes since last activity), and then update the active session ID cached at the server.
Now my issue is, a browser is holding an invalid session ID. What is the best point for me to inject a rejection or redirect to sign-in for this scenario?
I could modify the AuthorizeAttribute, but it seems like there should be a cleaner place to do this that won't require me to search and replace all my Authorize attributes, for example via a Global.asax event, or a controller event (I've already extended Controller in my project).
For example, if PreAuthorize existed, I would write some code there to test the request's cookies for a valid user/session ID pair, and if it didn't exist, I could simply remove the authentication cookie from the request, which would result in a standard unauthorized redirection.
So after a bit of research, it seems that a custom AuthorizeAttribute would typically be the correct approach. However, in my case, since I already had a custom role provider implemented, it was just a line of code to do it there. This also benefited me because I only wanted session concurrency for a single role. A side effect is that any use of web.config to control access to static files by role is also in-effect for session concurrency.

MVC3 mixed forms and Windows authentication

I currently have an intranet site that is accessed by external customers. I therefore set this up using Forms Authentication. However the powers that be (my bosses) want all our domain users to not have to enter their username and password to access the site.
I've done a bit or reading and everything seems to point to setting up a WinLogin.aspx page that you alter to use WindowAuthenthication and then redirect from there.
I have a problem with this as I don't like the idea of putting an aspx form in my mvc application.
Can anyone tell me how to achieve mixed authentication using a strictly MVC Controller/Action setup without a second application?
NOTES: running MVC 3 on an IIS 7 box.
Forms Authentication is not related to the URL or physical structure of your files. What matters is that a URL should ultimately map to a physical (or virtual) resource on the server, and be processed, and be returned back to the user.
Thus, somewhere in between for each incoming call (each HTTP request, even those for CSS and JavaScript files), you have to see if the current user has enough permission to access it or not. If no, then you might redirect him to the login page.
If you want, you can have a URL like /user/windowslogin where user is the name of the controller, and windowslogin is the name of your action method. Then you can create a custom authentication attribute (something like [WindowsAuthentication]) on your windowslogin action, and in that attribute (which is an MVC filter in essence), you can see if the current request comes from within your domain, and if so, talk to Active Directory for authentication or stuff like that, and on case of successful authentication, create an authentication cookie using FormsAuthentication class, and the rest of the story.
However, I don't think this would be an easy task. Others might introduce better solutions.

Downside to Forever Timeout in ASP.NET MVC?

As a user, when I see a "remember me" checkbox, I expect it to remember me -- not just when I close my browser, but when I come back to the site after a week.
So in my ASP.NET MVC application I am considering the following web.config values:
<authentication mode="Forms">
<forms defaultUrl="/" loginUrl="/account/login" name=".ASPXAUTH" timeout="50000000" />
</authentication>
I plan to also have userIsOnlineTimeWindow="20" to still have decent stats about who is online. I also plan to setup a machineKey so that the user isn't kicked off when IIS recycles.
Thoughts on this setup? My biggest concern is that it will hog up resources -- but will it in a stateless MVC app? Isn't that actually related to the sessionState timeout variable as opposed to authentication timeout? And sessionState is no longer relevant in MVC? I've seen conflicting information and am trying to get to the bottom of it.
Also, if I take this approach, I assume that this should also take care of the user who fills out a form for a long time before hitting submit and they lose their work. I've seen posts related to that, but am trying to solve two problems at once (keep alive while viewing the page plus also keep alive for days if I said 'remember me'.
One issue I see is that even if the user doesn't say "remember me" it will still remember them until they close the browser. (To me that's within user expectations.) The other issue is that I may need to perform extra checks on IsApproved and IsLockedOut per http://scottonwriting.net/sowblog/posts/11167.aspx.
Thoughts? Particularly on the system resources issue. Thanks.
FormsAuthentication is stored as a cookie in the client's browser and will not use up any resources by itself. The timeout setting there does not change how long something will be kept in the server's memory or anything to do with the regular session storage.
If you rely solely on the user ID/name you get from FormsAuthentication (HttpContext.User) then yes, there will probably be issues with administering user accounts like you point out. It would be a good practice to look up the actual current user data once per request.

ASP.NET MVC permitting only one logged in user

I have an experience with CakePHP and now started coding on ASP.NET MVC framework.
I have a problem with the login system. How can I restrict users from logging only one time simultaneously on my system?
I can create a field in my DB where Customer becomes active when logs in. If he logs out I can make active false. But what if the session just ends? How can I catch this?
This article provides a possible solution.
This is, unfortunately, something of a challenge due to the way that the session end event are implemented as you don't have access to the information you need when they fire.
So turn the problem on its head a little, if you track the session that they last logged in on then if you get a request from that same authenticated user in a different session then remove the auth for that session (in effect the older session) with an appropriate redirect to a suitable message.
The key here is tracking not only who is currently logged in but also the session ID for that login.
Details are a bit more complicated - but you can perform the test at a request level or by adding your own base page class, deriving all your "real" pages from that and checking in a page event.

Resources