Suppose each user has certain preferences that is saved in database for that user.
For example: UnitSystem, UILanguage, TimeZone,...
When an http-request is made we need to have access to user preferences (e.g UnitSystem, TimeZone, ...) to correctly process the data and render the view in the correct language.
What is the correct way to save/access user preferences during program execution?
Read the user preferences from database for each http-request
Read user preferences once when user logs into the application and save it in session variables.
Read user preferences once when user logs into the application and save it in a cookie.
How do you handle global settings in your MVC based applications?
In your case, I would probably store the setting in the session and cookie and check them in this order:
Check the session for the variable.
If not in the session, check the cookie and store cookie value in session.
If not in cookie, check database and store in cookie and session.
That way you should be able to handle session timeouts & users with cookies turned off pretty transparently while still maximizing performance by hitting the DB only when absolutely necessary.
Of course you'll need some mechanism to update the cookie and session as well if the user changes their preferences in the DB. Assuming these preferences are set in the same application, that shouldn't be too big of a deal.
This is what the Profile providers are for in ASP.NET. Take a look at the section of the MSDN documentation titled "ASP.NET Profile Properties Overview", located at:
http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
You could then create your own profile provider (if one of the provided ones doesn't suit your needs) which would load/save the profile data.
Related
I have two models doing login (Devise) in my Rails app - Admin and User, both currently use the default cookie store for session data.
I want to be able to identify an Admin session in AJAX requests coming in from the admin, for authorization of these API calls. I plan to do this by setting an encrypted cookie upon Admin login. When the AJAX API call comes in, I open the cookie, grab some identification from it and look for a matching existing Admin session in the store.
As I understand it, to do this, I must have session information stored in the back-end, either by DB or memcache stores.
I expect to have millions of sessions of Users and just a few sessions of Admin at any given time. For this reason, I don't want to just move all session information to a DB or memory, since this is a heap of unneeded data to store. I only want to store/look at Admin session data.
A solution will be creating some custom model which enumerates Admin user sessions, and is maintained by the app. This is simple enough but requires for instance, a way to clean up sessions when they die without signing out. Essentially this is an attempt to duplicate Rails's session store mechanism, which comes with all the problems of storing and maintaining sessions. Instinct tells me to avoid this solution. Am I correct to avoid it?
If so, then my question is, is there a way to configure multiple session stores in a Rails app, a different store for every logged in Model? In this case, have Admin sessions stored in memory, and User sessions stored in cookie. If not, I'll greatly appreciate any comments and suggestions.
Thanks!
You may be thinking about it wrong.
Session are a low level mechanism that you build your authentication on top of. Its just a cookie containing an identifier (a random hash) which is linked to a session storage (by default cookies). This is a simple mechanism to add persistence to a stateless protocol.
Confusingly we also use the concept "sessions" when talking about authentication - for example logging a user in is often referred to as "creating a session". This is complete poppycock as we are just storing a claim (often a user id) in the session that was created when the user first visits the application.
If so, then my question is, is there a way to configure multiple
session stores in a Rails app, a different store for every logged in
Model?
No. Thats a chicken-vs-egg conundrum. In order to know which session storage to use you would need to access the session storage to know which session storage to use... you get the picture.
While you could create your own session storage mechanism that works differently does this is most likely a complete waste of time. Premature optimization is the root of all evil.
As I understand it, to do this, I must have session information stored
in the back-end, either by DB or memcache stores.
Not quite true. You can perfectly well build an authentication solution with just the cookie storage. In that case Rails just keeps a record on the server of which session identifiers are valid.
The main reason you would need to store additional session information in the database or memcached is if you need to store more data in the session than the 4093 bytes allowed by a cookie. Cookie storage is after all much faster and does the job fine 99% of the time. YAGNI.
You should also recognize that not everything needs to be saved in the session storage. For example the Devise trackable module saves log in / out timestamps on the user table as part of the process of authenticating a user. This is "session information" yet has nothing to do with session storage.
I want to be able to identify an Admin session in AJAX requests coming
in from the admin, for authorization of these API calls.
There are many ways to use different authentication logic for different parts of the application such as Warden strategies. For an API you may want to consider using stateless (and sessionless) authentication such as JWT.
I have an application that has an actual map of objects that any visitor can view as long as they have the correct access code. I don't require the user to login because I don't want to make them create an account as it is unnecessary. I want to allow the users to mark the objects on the map with a check and save the edits within the session. So if the user refreshed the page or they close the application and reopen it an hour or so later, I would like to save their marks based off their session id. But I am confused on how to set this up without requiring them to login because I am unsure how the sessions would work.
Any help would be greatly appreciated!
Sessions in Rails work the exact same way regardless if you have a proper authentication system or not.
When a first time visitor visits your application the sessions middleware creates a session identifier. This is a cryptographic hash that is kept by the server and also passed to the user in a cookie.
This lets you identify users across requests.
This session identifier is also linked to a session storage. By default this is ActionDispatch::Session::CookieStore which lets you store session data in a encrypted cookie held by the client. This is where you would normally store a user id. Since its a cookie the amount of storage space is very limited. If you want to store more data in the session you can use a different store such as Memcached, Redis or ActiveRecord.
But what you may want to consider is creating (guest) user records implicitly without the normal sign up procedure. I would just use Warden and have a bare bones user model and a cron tab that cleans out unneeded data periodically.
This gives you a database oriented application model where you can use associations and build it like a standard rails application instead of the untestable mess that results when someone goes bonkers with sessions.
I would implement Cookies (with their permission of course). You can store basic data in it, or even create a sort of ID for them so when they return you can restore their settings
Because of the awesome EU directive on allowing users opt out from having cookies stored I have the following problem.
I have a message that displays at the top of the screen that asks the user to opt in or opt out.
if the user opts in, cookies are turned on using rack.policy, and the message is hidden. A cookie variable is set to say that the message should not be shown again for future visits. Perfect
If the user opts out. Cookies are disabled, fine. the message is cleared.... and a session variable is set to say don't show the message for this session. This would be fine, but it seems the session variable is saved in the same way as a cookie and the rack policy does not allow it to be displayed. The message therefore flashes up on every single page.
So first, thank you EU. Second, how do I save a "session variable" without saving to a cookie?
Unless you try going for something more exotic like local storage offered by the browser, you can't. The rails guide explicitly states:
All session stores use a cookie to store a unique ID for each session (you must use a cookie, Rails will not allow you to pass the session ID in the URL as this is less secure).
I'm no lawyer, but for what it's worth I believe that law is intended to apply to cookies used for marketing/tracking purposes and does not apply to cookies needed for the site to function like cookies used for authentication or ephemeral storage. With this in mind, you could use the rails's session cookie for must-have data and use separate cookies for other purposes that your application can disable.
I wouldn't take it as gospel, but this Wired article seems to a good job of providing a simplified explanation.
I am learning Rails by reading the online guide(for Rails v2.3). The guide is great, however, there is a confusion for me, that's:
there is a chapter explains the Session of Rails and another chapter explains Cookies of Rails. The explanation is easy to understand separately, but when compare the two, reader like me does not see the significant difference between Session and Cookies . Especially under which situation session should be used and under which situation Cookies should be used ?
Besides, in the session chapter, there is a concept of CookieStore , what is the difference between the CookieStore and Cookies then?
Could someone explain to me these?
Sessions & Cookies both hold the ability to store some information (e.g : the current_user id) in between two or more requests which (in http) are otherwise stateless.
But Session is more of an abstract concept related to the notion of being in a certain state for a specific amount of time : the info it contains can be stored in the database, in a server side file, in a redis hash OR in a cookie.
Cookies are always the little text file navigators have to store some persistent data in between requests... But having some data on the client side can be insecure so that's why it is often encrypted. But it's true the notion can overlap with session.
TL;DR : session the abstract concept of holding temporary data. Cookies one (common) way of doing it.
A cookie is a small text file stored in the browser.
A session is the concept of a state of being "in-use", and that state can have data associated with it. Rails keeps track of sessions with cookies, and lets you choose different storage for associated data and access it with the same session interface.
CookieStore means all the session information is stored inside the cookie itself. You can choose to use various other stores where appropriate, and it'll still be available with your session accessor methods.
In addition to the session, you can set other cookies to store information on the user's browser. These are not tied to the session and can be set, accessed and deleted independently.
Example 1, storing a logged-in user's shopping cart in a session:
session[:embarassing_products] = ['ooh',
'naughty',
'lucky_im_using_activerecord_store',
'only_the_session_id_is_in_the_cookie',
'other_data_arent_in_the_browser']
The shopping cart is preserved for the user's session. You can set the session to end when the browser window is closed, when the user logs out, or when a certain amount of time passes.
Example 2, remembering a browser's last language preference for your domain in a cookie:
cookie[:lang] = 'en-US'
This information is stored inside the cookie itself. Unless the cookie expires or is deleted (by you or the user), it stays inside the browser.
As to me the main difference is that the session data stored on the server, whereas the cookies are stored on the client (browser).
So you can trust the data from the session. Information from the cookie can be manipulated, stolen, and thus should not be relied on for critical use (for right access for example).
Second point, is that cookies have a limited size, and are only text-based. You can store in session many complex objects (but beware of memory consumpation), and you don't have to transfer them to client then back at each request.
And typically the session only persists until the user shuts down their browser. That's useful for typical logins. Whereas if you needed information to persist between sessions you could use a cookie with a longer duration, for example a 'remember me' flag that persists even after the browser is restarted.
how should I store user data in asp.net mvc? Let's say a user want to see 50 records per page. I wanted to save it in Session, but if I am doing it right, the Session resets every time a new controller is initialized. So where? A cookie?
Typically the session is not reset on controller initialization! Make sure you aren't clearing the session from code.
Anyway, storing this in session cause the record-limit to be reset quite often (depend on the session timeout param).
Consider storing this in the user's profile kept in database (will be used after log in), or in cookie (don't require login to be used). This will keep this setting forever - your users will appreciate that :)
Instead of using the built in ProfileProvider-system in ASP.NET, which you should only use i you want to persist user settings across multiple visits, you could instead put a the settingsdata in the session. Maybe wrapped in a serializable object.
Session is cleared if
you clear it in your code
the cookie storing the sessionid expires (depends on your settings i web.config) (if a
cookie expires during a session, it does not truly expire before the user closes all browser windows)
if the application is restarted (unless you use sticky sessions (DB based sessions) in which case sessiondata persists through application restart)
Session does not reset when a new controller is initialized. But it does when you leave the application (your session ends) or the application is restarted. You should use Profile to store this kind of information.
See this:
http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
http://www.odetocode.com/articles/440.aspx