Is it possible to pass a session via a hidden form field? (ie POST)
if so if it possible to between the standard method and field sessions on a per controller bases without losing information?
If cookies are disabled, CGI:Sessions will automatically switch to using hidden fields, however, I'm not certain exactly how this behavior is supported in Rails. Moreover, changing this behavior to require the use of hidden fields may require modifying CGI:Session.
If the client has cookies disabled, the session id must be included as a parameter of all requests sent by the client to the server. The CGI::Session class in conjunction with the CGI class will transparently add the session id as a hidden input field to all forms generated using the CGI#form() HTML generation method. No built-in support is provided for other mechanisms, such as URL re-writing. The caller is responsible for extracting the session id from the session_id attribute and manually encoding it in URLs and adding it as a hidden input to HTML forms created by other mechanisms. Also, session expiry is not automatically handled.
Therefore, it should be possible to use this method, but as far as I know, it's not supported as a simple option in Rails.
To be clear, even ActiveRecord Session Store uses cookies, so don't equate session stores with how session data is handled by the client.
Finally, at one time there were plugins to support this behavior, but these plugins are old, don't appear to support Rails 3. See the "Non-cookie session" section of Sessions & Cookies in Ruby on Rails
Related
I want to store a non-critical non-confidential piece of information in the user's session in a Ruby on Rails app. The user model is set up with Devise. How do I do this? Various guides give conflicting and incomplete information about it. session[:foo]? user_session[:foo]? Do I need to set something up to be able to use whichever it is - e.g. get a gem, config something, or insert any lines before setting the session variable?
To provide context - the user may be creating multiple new items back-to-back, so it would be nice if the new form remembered and pre-selected the category based on what they selected previously. If there's a better way to do this, I'm open to suggestions. I'm new to all this. Thank you!!
Are session variables in 'session' or 'user_session' in Rails?
The simple answer is the session variables is named session.
A session usually consists of a hash of values and a session id, usually a 32-character string, to identify the hash. Every cookie sent to the client's browser includes the session id. And the other way round: the browser will send it to the server on every request from the client. In Rails you can save and retrieve values using the session method:
session[:cat_id] = cat_id
Category.find(session[:cat_id])
You can read this Rails Guide about session.
ActionDispatch::Session::CookieStore
The default Rails session object is accessible via the session helper method. It gives you an access to some chunks of data and is bound to a cookie value stored in your browser.
The user_session helper is provided by the Devise gem. It gives you additional security by restricting access to specific session data while user is authenticated on a server.
I am developing a web application using rails and devise for the authentication. There are two types of users, one who are able to have multiple concurrent sessions (super) and the others who can only have a simultaneous session (normal). In order to implement this behaviour, I have added a new field on the User model to store the authentication_token (generated in the SessionsController#create). Also, I added a new filter to the ApplicationController which check if the stored token in the session is equal to the saved on the User model when it is a normal user. When it is not the same authentication token, we logout the normal user.
Now I am developing a new ionic mobile application which needs to login to the same rails application. However, in this case all user types can have multiple concurrent sessions. In order to do this, we would like to continue using devise (although we have also considered to use doorkeeper with password flow).
I am not sure about the best approach to get this. The main problem is to detect if we are accesing the API with the rails or ionic application. One approach is to add a parameter but I don't like to use a parameter in all requests. Another approach it is to use browser gem, but we can access the web from a browser in the mobile.
When we uses the rails application, we can use the same behaviour described above. Otherwise, I think it is not necessary to do anything because devise permits concurrent sessions by default.
Another posibility it is to use a new model to store the authentication token and its type (rails or ionic). If we are using the rails application, then we query the rails authentication token and override it (or create if it does not exist). On the opposite, we add the new authentication_token as a new instance related with the user model. With this behaviour we can manually control the expiration of the tokens and store more information (IP, browser...).
I am not sure about the best approach to achieve this behaviour. Thanks in advance.
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.
How does one protect against XSRF attacks in Grails. I see that forms support the notion of useToken which (I think should suffice). However, remoteForm or other AJAX related request don't support this feature.
Also, is there a way to invert the functionality of useToken so that it is always used rather than enabled on a case by case basis?
You could try looking at the source code of the <g:form> tag. It uses a SynchronizerToken to create a token and store it in the session. Based on the resolution of this issue it should be possible to use the same token for all forms on the same page. I did not try this, but theoretically you would just need to manually create a hidden field on the form and generate the token in that field.
We have inject a hidden value to the request object in a before filter and encrypt the value with a specific key. We then inject that request.token value to every form on the site and when we receive a POST we have a before filter to verify that that hidden field is present and its value can be decoded by that same secret key.
If that hidden value is not present or if it is stale -- we use a timestamp as payload -- we give the client an error status.
This is an alternative way to what was described above and we use this, because we do not use sessions on our sites to make it easier to load balance.
My understanding of the session lifecycle in Ruby on Rails (specifically v3 and upwards) is that a session is created at the start of a request, for each and every request, and if that request doesn't carry an existing session cookie a new one will be created, otherwise the session cookie is deserialized and stored in the session hash.
The purpose of this, of course, supports a number of security features such as CSRF etc.
However, this poses a bit of an issue when it comes to caching of pages in a site with HTTP cache services and proxies such as Varnish, as most of the configurations tend to strip out these (generally all) cookies on both the request and response end (as the cache is usually intended for a generalized audience).
I know that it is possible to setup Varnish etc to create the object hash with the cookie details included, and this would scope the cached data to that session (and therefor that user), however I am wondering if this is completely necessary.
I have an application which is fairly 'static' in nature - content is pulled from a database, rendered into a page which can then be cached - there are a few elements (such as comment count, 'recent' items etc) which can be added in with an ESI, but for every request Rails still tends to want to setup a new session, and when a user already has a session this stuff is stripped out by the cache server.
I am wondering if it might be possible (via pre-existing functionality, or building the functionality myself) to allow the developer to control when a session is required, and only when that is specified is the back-and-forwards with cookies, session initialization/deserialization etc necessary.
That, or I am thinking about this problem the wrong way and need to address the issue from another angle...
From what I know rails sessions can be controlled fairly in-depth via ActionController::SessionManagement
http://ap.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000070
There are examples in the API docs of disabling it per action, per controller, etc.
If your site is mostly static then you may want to use full page caching. This takes Rails out of the request entirely and let's the web server deal with it once the content has been generated. Might cause some serious headaches depending on your exact needs as far as the comment counts and user-specifics though.