Unable to store and access Session Variables in Rails 4 - ruby-on-rails

I am trying to store session simply by doing session[:user_id] = 1. When I access it in next line by doing puts(session) it prints <ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash:0x0000010433dda8>
I m also not able to fetch session[:user_id] in other pages.

You are using NullStore. Just configure other store (file, memcached, etc.)

Related

How OpenStruct stored in session

I have some controller. In this controller I get OpenStruct object and want to save it to app session. Next code works fine:
session[:info] = OpenStruct.new(first_field: 1, second_field: 'two')
p session[:info] right after this line prints
#<OpenStruct first_field=1, second_field="two">
But after this I do redirect to another controller, and when I write p session[:info] in this controller I get
{"table"=>{"first_field"=>1, "second_field"=>"two"}}
So, why do I get this, and how can I load correct OpenStruct instance?
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.
You should either serialize your objects before storing them in the session.
session[:info] = OpenStruct.new(first_field: 1, second_field: 'two').to_yaml
and retrieve it using
YAML.load(session[:info])
from the rails documentation
Do not store large objects in a session. Instead you should store them
in the database and save their id in the session. This will eliminate
synchronization headaches and it won't fill up your session storage
space (depending on what session storage you chose, see below). This
will also be a good idea, if you modify the structure of an object and
old versions of it are still in some user's cookies. With server-side
session storages you can clear out the sessions, but with client-side
storages, this is hard to mitigate.
or change your session store from cookie_store to cache_store
In your environment change
config.session_store :cookie_store
to
config.session_store :cache_store

Where is the Session Stored in Rails?

In Rails, I have implemented the below code for user auth (confirmed to be correct). However, I wanted to confirm my thinking for this strange session[:session_token]. is this the "cookie" that is stored in the browser?
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user, :signed_in?
private
def current_user
#current_user ||= User.find_by_session_token(session[:session_token])
end
def signed_in?
!!current_user
end
def sign_in(user)
#current_user = user
session[:session_token] = user.reset_token!
end
def sign_out
current_user.try(:reset_token!)
session[:session_token] = nil
end
def require_signed_in!
redirect_to new_session_url unless signed_in?
end
end
My understanding so far of how this works is that whenever the browser/client sends a request to rails, the cookie (with the session[:session_token]) is also sent over, thus allowing the current_user method to find the user. Is my understanding correct? This is strange to me because there's a gap of knowledge of how exactly the browser/client gets access to the session cookie when we declare it in ApplicationController (Rails-side).
You are pretty much there. Although, I have a feeling you might be confusing apples with oranges...
Sessions:
Very often in dynamic web sites one would want to store user data between HTTP requests (because http is stateless and you can't otherwise associate a request to any other request), but you don't want that data to be readable and/or editable on the client-side inside of the URL (like.. yourwebsite.com/yourPage?cookie=12345&id=678), and so on..., because you don't want the client to play around with that data without passing through your server-side code.
One way to solve this problem is to store that data server-side, give it a "session_token"(as you called it), and let the client only know (and pass back at every http request) that token. This is how the session is implemented.
Cookies:
The most common technique for implementing sessions in Rails involve using cookies, which are small pieces of text placed on the user’s browser. Because cookies persist from one page to the next, they can store information (such as a session_token or whatever else you want) that can be used by the application to retrieve the logged-in user from the database.
Where is the Session Stored in Rails?
Using both of the above concepts I can now tell you that the default session store inside of Rails is CookieStore, which is about 4KB in size.
To put it simply...
def sign_in(user)
#current_user = user
session[:session_token] = user.reset_token!
end
...method that you defined places the user into a temporary session.
Then the idea is that the following...
def current_user
#current_user ||= User.find_by_session_token(session[:session_token])
end
...method would find and retrieve the user from the database corresponding to the session token and initialize it to a variable you specified.
Additional info:
You should also note that there is an important difference between Rails's session and cookies helper methods...
They both generate cookies, however, session[...] method generates temporary cookies, which should expire upon the browser exit, and cookies[...] method creates persistent cookies, which do not.
Additionally, I would suggest having a look at Section 2 of Ruby on Rails Security guide. You might find it useful.
Hope this helps you out.
Session is stored in server side. And,
Cookie is stored in client side (in browser cookie). And,
When client/browser send a request to rails server, every time cookies are sent to rails server.
When a session is set in rails server, like: session[:user_id] = 4,
Rails store it in server side.
Session is saved in server side like key value pair (like json object)
For each browser, Rails set a session identifier in cookie, so that, Rails can find the correct session information for a request.
Without session identifier in cookie, Rails do not know, what session belongs to what browser.
So, session will not work without cookie.
Edit: Explain: sessions are stored server side
Suppose, I am using your web application, and after login I will be redirected to home page.
I open login page, input username and password, and click login button.
The form is submitted to sessions#login action.
in sessions#login - you check username and password - and set session[:session_token]:
if username and password is correct
random_unique_identifier_string = #user.remember_token
session[:session_token] = random_unique_identifier_string
redirect_to root_url
end
When server run this code session[:session_token], server need an unique identifier for each browser session.
So, server generate an unique identifier for this browser, such as: abc123
Server set all session variables in a place (may be in some folder or in database), label this folder as abc123.
Now server send a cookie request to browser - to set cookie _ebook_session = abc123.
(I see, if my app name is ebook, in rails, cookie name is like: _ebook_session)
Now the page redirect to home page.
** Note: Everything above happen in single request **
Now, in my browser, I want to open some page that need authentication (suppose, dashboard page).
You added before_action: require_signed_in! in dashboard controller.
So, when I open dashboard page in my browser, browser by default send all cookies with every request. so _ebook_session cookie is sent to server. Your server gets the value of _ebook_session cookie is abc123. Now your application know we need to look in abc123 folder for session. Now you can get value of session[:session_token] from abc123 folder.
** I have explained second request above **
Each browser needs unique session identifier.
Important: _ebook_session cookie will be set in browser in first request. If we already have _ebook_session cookie set in a browser, we do not need to set it again, second, third and next requests in that specific browser.
I hope, you understand.

Rails + Cucumber: How do I delete the session but keep the cookies?

How do I delete the session but keep the cookies? I'm trying to simulate a browser close/reopen.
In your step definitions you can access the session directly and remove any/all of your critical values. Assuming that you're trying to test login/logout you could remove the user_id value from the session.
session[:user_id] = nil

Session in Rails vs Session in rhodes

In Rails its easy to store and retrieve session variables.
for e.g
session[:user_id] = #current_user.id
I was wondering if there is something this like in rhodes too.
Like in rails request parameters are accessible through
params['name']
while in rhodes its
#params['name']
If there is nothing like session variable, can anyone suggest some work around for managing sessions. like using global variables that are available across multiple requests.
Comments/Hints, please?
thanx.
I implemented my own session in rhodes.
Assuming that a rhodes app will have only one user you don't need to detect in wich user or "session" you are, so you will have only one session.
I created a global hash, named $session, where you put and get your values:
In the application.rb I put this:
$session ||= {}
And I use it thus:
$session[:user] = 'john'
puts $session[:user]
You could also store persistent values in the Redis database as a key/value pairs database.

Rails 3 Cookie Based Sessions Question

With Rails 3, the default session storage mechanism is cookie_store. I assume that this means that the contents within the session hash are serialized, encoded and stored within a cookie in the browser? Does this mean that nothing (or very little) of the session is stored in the server?
I've had a few issues where I had a cookie overflow error and I'm assuming because I kept on adding to my user instance (which was also linked/fetched from the cookie).
u = session[:user]
u.add_this lots_of_data
so eventually I got a cookie overflow error.
Am I correct about this? Are sessions fully stored within cookies in Rails 3 (by default)?
Yes, if you use the cookie store, the session data is stored in the cookie. If you'd like to store it on the server, you will need to use another session store.
However, if you are storing model objects or "lots of data" in the session, you are most likely doing it wrong in the first place. Your data should go to the database, and the session should only contain as much information as you need to retrieve it.
In you case, this would mean to store the user id int he session, and load the user from the db in a before_filter.
Yes, you are right. The problem might come up if you keep on adding data to session.
But there are some other things that affect it.
Once, I ended up with CookieOverflow error, and the reason was the flash[:notice] messages.
If you use flash[:notice] = "message" and then redirect, the text "message" will be stored in the cookie. If the size of the text u pass is more than 4KBs, you get "CookieOverflow" error

Resources