I am working on a small web application right now and part of the requirements is to allow the user to pick how their session will be managed: with either cookies or HttpSessionState. I have researched how to use cookies (http://www.codeproject.com/Articles/31914/Beginner-s-Guide-To-ASP-NET-Cookies) and Sessions (http://msdn.microsoft.com/en-us/library/ms178581(v=vs.100).aspx). I will be using non-persistent cookies.
The application will collect some data about the user (name, age, school) and take this session data and display messages on another page depending on the data that the user entered.
The thing I am having problems with is how to deal with how the user will pick the management. That information is also part of the session! The selection will be checked on every page on the web application.
I have researched globals (http://www.dotnetperls.com/global-variables-aspnet) but that is not a good method because it can be shared among different users which is not what I want! Correct me if I am wrong. How can I store this data temporarily through the session without actually using a session or a cookie?
Is it even possible to do this with cookies and sessions being mutually exclusive?
At the end of the day, you should save it somewhere. This option if it is not persistent, as it may be asked/changed by every time user visits the web site, the easiest way is to save it in a hidden html field. As user submits the forms, the value will be passed to the next page if you are using html forms. Or you can retrieve the value and send it manually in asp.net (e.g. Transfer).
You may use ViewState (not recommended) as well. If the information should be persister for future, try using User Profiles in ASP.net and save it as a custom field in database. This one is really cumbersome.
Related
This question applies to both ASP.NET webforms and MVC apps. I have a checkout process where there are two forms Form A (address page) and Form B (shopping cart page). The normal happy path works where the customer completes the Form A and then click submit button which takes him to the Form B.
The customer can accidently visit the Form B without ever visiting the Form A or completing the information. How can I find out whether the customer has completed the Form A if he access the Form B directly? If he has not completed the Form A, I want to redirect him to Form A. Is there a ASP.NET framework object that I can use for this purpose?
The only foolproof way is to save something to a database that indicates that the particular user has completed Form A. This could be actually storing some entity that is created by Form A or just some sort of log. The key is that you'll need to associate with the user, which means the "user" must actually have an account and be logged in. If it's anonymous, there won't be any real way to track them.
With this set up, then, you'd simply check in your database that the user has a record indicating they've completed Form A in the controller action for Form B. If nothing exists, you redirect the user to Form A. Otherwise, you allow them to view Form B.
And alternate approach is to use Session or set a cookie to indicate that Form A has been completed. There's pros and cons to both of these, and neither is foolproof. With both Session and a cookie you can track anonymous users, so you don't have to force a login. However, Session is not a permanent data store. By default, it will expire after 20 minutes of no activity, and even if you bump that timeout up significantly, it's always going to be finite.
Additionally, depending on the session store you use, it can also be very volatile. In Proc is the default, as it requires no configuration. Everything is stored in memory, but if the server restarts, App Pool recycles, etc. then all the session data is lost. It is possible to configure it to use something like SQL Server, though, and that would be very stable. Either way, you'd still have the timeout issue to deal with.
With cookies, you can set a far-future expires cookie that would effectively be permanent. However, cookies are stored client-side and can be removed by the user. They can also be manipulated (either created manually or modified). This means if a malicious user figured out how you were tracking whether Form A had been completed, they could basically fake that, and make your site think they had completed Form A, when they had actually not. Now, whether any one would care enough to do that is an entirely different matter. Still, it's something to consider.
Finally, both Session and cookies can effectively be disabled by the user. Session actually uses a cookie to store the session id, so if the user disables cookies in their browser, neither approach will then work.
Your best bet is still forcing a login and storing something in a database to indicate that Form A has been completed by that authenticated user. However, if you can deal with or mitigate the downsides of using Session or cookies, then those might be viable options.
Hi so this probably has a very simple answer..
So my question is I'm using formsauthentication with webmatrix in asp.net razor pages.. what my application does is let one user have multiple "subscriptions" and when the user logs in they get to select what "subscription" they want to log in as now the problem is I want the user to be able to have two windows open and have different "subscriptions" on each window.
If I'm storing the current subscription in the session cookie then they will always be the same subscription.
Is there a way to distinct the two browsers? (Keep in mind this is not a one page website so I do need to have some way of storing the subscription id so I can show the right data for that specific instance)
I don't think you'll be able to do it with the basic aspxauth cookie, since it is issued per user, i.e. per log in. The same with the session cookie, which is shared between the browser instances. Since you support multiple "subscriptions" per user, you'd have to track them manually in each page post.
I have built an ASP.Net MVC site using Forms Authentication for a client.
Recently, they have requested that an authenticated user be restricted to a single browser session. That is, if the user raises a new browser instance, or opens a new tab on the original browser window, that he/she be logged out of the original. They insist on the added security.
Does anyone know how I might approach this? Thanks in advance.
Personally, I would push back and ask exactly what security this is bringing. Maintaining state like this counter to web architecture and is only going to bring you and your users grief.
Here is what I would do if presented with this problem:
Store the username of the user in your database (i.e. LoggedOn table).
When a user logs on, check to see if their username is already present in the LoggedOn table.
If the user isn't already logged on, insert a row into the table with the username and the current time; otherwise present the user with a message informing them that they can only log into the system from one device at a time.
Include logic to expire and delete the rows in the table if a user's session expires or if the user logs out.
First a disclaimer: I'm no expert in web programming.
Perhaps you might try a system where every user interaction requires the submission of a random value that's been generated for that page (much like what's used for CSRF protection.) That key could be kept under the user's session information on the server, and if a page is ever requested without the correct key as a URL parameter, the session is invalidated. The URL from one browser won't work in another, either, since once a URL is gone to, the user's session key has changed. The only way for a user to transfer a session between tabs would be to copy the URL of an unclicked link and paste it in a new tab's address bar. Switching browsers would be even more complex assuming that ASP.Net uses a session cookie: the user would have to transfer the cookie from one browser to another. Going back would also fail, as all the links on the previous page, and the URL for the page, would carry an incorrect session key.
Also, for reference, I believe the US Gov't TreasuryDirect site works in the way you've described, though I've never looked at how they manage it.
Thanks, people for the suggestions. Each had strong merits, however I had to take a hybrid approach. I found an incredibly simple suggestion from this post.
I implemented table of active users as Karl suggested as well. This will give the client the ability of deactivating the user on demand.
Thanks again.
Think of it as one active view at a time instead of one browser or tab. Or convince the customer to view it this way.
You can always issue a unique cookie for the browser session (ASP.NET Session) and allow communication to the latest cookie issued effectively making only one session active at a time, and therefore rendering other open sessions (browsers, tabs, etc) useless with the app by disallowing them communication any longer or serving up an error page for them. To do so you have to recognize who the user is and authenticate them against your app. This is half the puzzle and will force the user down to use your app in only a single browser at a time on their machine.
The other part of the problem is to pare down the windows and tabs that are part of the same browsing session of that browser, to allow only one view to be active at a time. To do so you can issue a unique sequential ID to the viewstate of each page for postback to the server to uniquely identify that page apart from other pages sharing the same session state (whether that page be in a browser tab, a frame or new window, etc). Or a code of your choice that's traceable. You then know which page is posting back within the session and can disallow others or deactivate previous ones by, again, shutdown down communication in some manner or serving up an error page, etc.
A new browser instance or a new tab may or may not be part of the same browsing session depending on how the browser is configured. I believe, for example, IE provides a setting that allows the behaviour to be set of whether a tab opens in a new process or session or shares the session. You won't necessarily get expected consistency across browsers to rely on for this feature, therefore you need to take programming steps to reign it in, like those described above.
You can additional steps like disallowing the user to be connected from a different IP# at the same time.
I've recently been developing a website using asp.net webforms that uses in proc sessions and I noticed that session ids are shared amongst browser tabs. So I was wondering what you would do for the following situations:
Problem:
Multiple logins with different users in the one browser problem
User opens browser tab 1, logins
with "user1" - store in
session
User opens browser tab 2, logins with "user2" - store in session
At this stage session information is now pointing to "user2" because of how session id is shared amongst browser
tabs
User tries an action on tab 1 and suddenly they have "user2"
information
How do you alert the user in tab 1 that the user has changed or how do force tab1 user to logout?
My initial thought was to keep a list of active users with session id via database or application object, but the problem I face is that in tab 1 what am I going to compare the list against, when I do a request the HttpContext.Current.User would be updated with "user2" how do I know browser tab 1 was initially for "user1"
Appreciate anyone letting me know of any alternatives or best practices for the above problem
Regards DotnetShadow
Why don't you warn when user2 logs in instead? With a message like "You are already logged in as user1, are you sure you want to login again as another user?"
All tabs in a browser belong to the same instance, so all tabs share cookies and sessions, there isnt much you can do about it. If you want to implement this badly the only solution that comes to mind is carrying a unique session id with each URL. Based on that unique id you can link a specific user. You will need customize the session logic and would have to make sure all links in your website carry this unique id. It could be done with alot of effort but the real question is , is it worth doing?
Some have suggested adding uniquifiers into the URL, and tracking based on those.
If you're going to do this, you may as well just let ASP.Net do this for you by turning on cookieless sessions - it then uses the URL to contain the session ID.
That's just how it is. You can't do much about it. Users are now accustomed to this behavior as it is consistent among famous internet sites like gmail, etc... so it shouldn't be much of a problem to them.
What I do to avoid this problem is redirect to append a short, random in-url login-identifier.
Then, rather than use session directly, I store a strongly typed object in the session vars under the random in-url code, and use that object for session storage. If you want to keep it simple, you could use a Dictionary. In addition to the normal session timeout, you should keep track of the last usage within each login-id and manually time-out a session if it's too old to avoid new users from keeping old logins alive.
Essentially then, each ASP.NET session corresponds to any number of login sessions.
This has the following advantages:
You can log in as multiple users simultaneously. That's handy to be able to do for many sites.
In public terminals, it helps avoid accidental session hijacking. When a user leaves a public terminal, closes the webapp tab but not the browser (which is quite common) and another person then approaches that terminal and opens a new window or tab to your site, this new user sees no trace of the previously logged in user. Of course, users should log out, and anyone can inspect the history, but there's no reason to invite abuse.
CSRF attacks against your site are a little bit harder since a url without the random login-id is meaningless.
The implemenation is quite simple if you use a hashtable - after all, any sessionstate-consumer already is written to store and retrieve data from a hashtable, you just need to change the hashtable it's using and should ideally include a custom timeout.
The obvious downside is that you need to include the random code in the url; and that you need a bit of extra implementation. You might hide the extra code using an iframe and/or javascript+XHR based site, but doing so is a much more invasive change to a site. Finally, note that cookieless sessions are not the same; though they're simpler to turn on, they involve a much longer less human-friendly url token, and by lacking the normal cookie session token, also are less secure vs. session hijacking (since suddenly any other program or even machine that discovers the session ID can pretend to be that user).
How about storing the data in viewstate? That would be unique to every window.
In my application I have the requirement to store, for the period the user stay logged in, some variables that's used to provide a customized experienced on how the user views it's data (pre-defined filters, language, etc.). My needed data is not more than 1Kb.
I have read many blog posts that definitely encourage to not store this data in the Session object. In many of these blog posts the authors suggests to use TempData instead.
As I understand TempData is a good choice for short-lived temporary data and not suitable for caching data during all the period the user stay logged.
Does am I wrong? What is a good alternative suitable to my scenario?
thanks for helping :)
Two options:
Cookies
Database
If this information needs to be stored only for the time the user is logged in and you don't want to persist it when he comes back cookies would work just fine. If on the other hand you want to persist the user's customized settings then you need to store them in the database or use persistent cookies.
Session is also an option but be careful if your site runs in a web farm - in this case you will need an out-of-proc session persistence.
As I understand TempData is a good choice for short-lived temporary data and not suitable for caching data during all the period the user stay logged.
You are absolutely right. TempData should be used only in the following scenario: a user calls a controller action, this controller action stores something into the TempData and immediately redirects to another controller action (it never renders a view) which fetches the stored data and renders a view (Redirect After POST scenarios).