I am new to ruby. I want to know when/where the Current user set. I know cookie will be generated for each URL request. And where the session details are stored? And where the current user set(in which file). Any one please explain briefly.
Hope you have a users table in your Rails application, so devise will automatically load all columns of users table in current_user.
It all depends on how you implement it. If you're using a library like Devise it has its own implementation, but usually such things are stored in encrypted Rails session store and on every request 'session' controller verifies visitor's cookie and only after that current_user is set to the User object from the session.
i prefer it in applicaton_controller..so that i can check where user_signed_in on every request and check the session ..if it exits then its ok else redirect_to login page..
for example in application_controller.rb
before_filter :check_current_user
def check_current_user
if current_user
#check if current user exists in our session
session[:current_user_id] = User.find(session[:current_user_id]).id
else
#if not ,then create new and set it to the session and return the current_user as u
session[:current_user_id] = User.create(:username => "guest", :email => "guest_# {Time.now.to_i}#{rand(100)}#example.com")
u.save!(:validate => false)
session[:current_user_id] = u.id
u
end
end
the above code is not perfect though..but i just wanted to show how current_user can be implemented to check current_user on every request using session and sets it in the session if there is no current_user as guest...
Related
I am trying to use session mechanism to store information of an user that is logged like this: session[:user_id]=#user_id , and that its ok.
But when a new user login in the app, the variable session[:user_id] is updated to the new user id, making the first one perform requests with an invalid id.
I used different browsers, private browsers, a browser in a Virtual Machine and another one in the host, and still got the problem.
I appreciate some suggestions. Is it normal the session being shared between multiple users? There is another way to store some specific data, and prevent the share between users? I thought that session was unique, why that variable is changing? The same happens for cookies variable.
EDIT:
application_controller
def sign_in
if(password != "" && #user_id!= "" && jenkinsip != "")
#client = JenkinsApi::Client.new(:server_url => jenkinsip, :username=> #user_id, :password=> password)
if(#client.get_jenkins_version != nil)
session[:user_id]=#user_id
end
end
end
in html
Every time session[:user_id]=#user_id is called, the session[:user_id] is being set to whatever the #user_id variable is set as.
Try using||= instead of =
set the session withsession[:user_id]||= #user_id to only set session[:user_id] to #user_id when session[:user_id] is undefined.
Follow the excellent answer of koxtra and
also have a look on devise gem for the user authentication.
Devise will do everything for you like users signin, signup, creating sessions and many more functions. You have to only install the Devise
in your rails application.
My book says to run "rails g controller sessions" and edit it as
class SessionController < ApplicationController
def create
user = User.find_or_create_from_auth_hash(request.env['omniauth.auth'])
session[:user_id] = user.id
redirect_to root_path
end
end
What is session[:user_id]? If X is controller, Y and Z are some string, can I define as X[:Y] = Z?
The session[:user_id] is a special variable, that can be accessed like a hash,, storing all information you store into your application's session.
You can read more about the session in Rails here: http://guides.rubyonrails.org/action_controller_overview.html#session
It's basically a Hash that's shared between requests to store information and re-use it in sub-sequent requests.
session[:user_id] is a variable, that you earlier need to store and then reuse it throughout your session.
F.e. You have authentication and then you have to jump through pages, that needs user_id. So you can use session, to store it there. You can find more info there http://guides.rubyonrails.org/security.html.
No. session is just an object which respond to [](key) method. You cannot define something like controller[:foo] = 'bar'
I was trying to disable multi login for single user using devise authentication and came up with this solution.
I used active record session store, so that I can access all user session by their ID. Changed initializer session_store.rb to
MyApp::Application.config.session_store :active_record_store
added field session_id to user table and created model for session(session.rb)
rails migration:
rails g migration add_session_id_to_users session_id:integer
session.rb:
class Session < ActiveRecord::Base
end
Since, devise gem using warden I set callback after_authentication to check user session.
user.rb:
class << self
def delete_session(session_id)
begin
session = Session.where("session_id=?",session_id)
session.delete_all
rescue => e
end
end
end
Warden::Manager.after_authentication do |user, auth, opts|
unless user.session_id == ""
auth.logout
User.delete_session(user.session_id)
user.session_id = ""
user.save
throw(:warden, :message => "User already logged in, try again wil singout from other machine")
end
end
This callback will alert when user already logged in.
I was storing user session id in application_controller before_filter (aplication_helper.rb)
before_action :save_session
def save_session
if user_signed_in? && current_user.session_id == ""
current_user.session_id = request.session_options[:id]
current_user.save
end
end
I was getting session ID by request.session_options[:id].
This setup works fine without any problem. Guys can you please share your suggestion on this implementation. Any potential problem will occur by this solution?
There was a similar question,
Devise - Invalidate user session if the same user logs in from a different browser/machine
The basic idea is the same, differently implemented.
Personally like it since its all neatly in the controller rather than in the model.
Is there a way to limit the number of sessions in Ruby on Rails application (I'm using Authlogic for authentication)?
I would like to allow only 1 session per user account. When the same user is logging on another computer the previous session should be expired/invalidated.
I was thinking about storing the session data in database and then deleting it when a new session instance is created but probably there is an easier way? (configuration option)
I just ran into a possible solution, if you reset presistence token you can achieve the intended behaviour:
class UserSession < Authlogic::Session::Base
before_create :reset_persistence_token
def reset_persistence_token
record.reset_persistence_token
end
end
By doing this, old sessions for a user logging in are invalidated.
Earlier I implemented it as you mentioned: add a session_key field to the users table and make sure that the current session_id is stored for the user on login:
class UserSession < Authlogic::Session::Base
after_save :set_session_key
def set_session_key
record.session_key = controller.session.session_id
end
end
Then in the generic controller do something like this to kick out a user when someone else logged in with that same account:
before_filter :check_for_simultaneous_login
def check_for_simultaneous_login
# Prevent simultaneous logins
if #current_user && #current_user.session_key != session[:session_id]
flash[:notice] = t('simultaneous_logins_detected')
current_user_session.destroy
redirect_to login_url
end
end
i do exactly what your talking about, assign a session id to each uniq session, store that id in a cookie and the associated session data in a table. Works well. My aim wasnt to limit users to a single session, but rather keep the session variables server side to prevent user manipulation.
I am trying to create a session explicitly like this UserSession.create(#user, true) but the session is not getting created, current_user is nil.
But when I do this, I get < #UserSession: {:unauthorized_record=>""}>us = UserSession.create(#user, true)
RAILS_DEFAULT_LOGGER.info(us.inspect) #=> UserSession: {:unauthorized_record=>""}
I had a look at Authlogic::Session::UnauthorizedRecord here it says
Be careful with this, because Authlogic is assuming that you have already confirmed that the user is who he says he is. For example, this is the method used to persist the session internally. Authlogic finds the user with the persistence token. At this point we know the user is who he says he is, so Authlogic just creates a session with the record. This is particularly useful for 3rd party authentication methods, such as OpenID. Let that method verify the identity, once it’s verified, pass the object and create a session.
which is exactly what I am trying to do (i am authenticating using omniauth and creating session using authlogic).
How do I fix this, so that I can get a valid session in current_user ?
I had a similar issue caused by the persistence_token being nil on the user. Reset it before creating the UserSession. So...
#user.reset_persistence_token!
UserSession.create(#user, true)
I'm not sure about the .create(object, bool) method signature, but the following works using authlogic.
class Api::ApiBaseController < ApplicationController
protected
def verify_token
return false if params[:token].blank?
#session = UserSession.new(User.find_by_single_access_token(params[:token]))
#session.save
end
end
If that doesn't work for you -- I think the #user isn't being set correctly.
If you map the active_record_store to the authlogic user_sessions table your session information will be stored in the database, and you will be able to store larger sets of data.
Inside your config folder:
config/initializers/session_store.rb
Comment out App::Application.config.session_store :cookie_store, :key => '_App_session'
Add or uncomment App::Application.config.session_store :active_record_store
Inside of config/application.rb
At the end of the class for you application add:
ActiveRecord::SessionStore::Session.table_name = 'user_sessions'
Restart your app, and any information stored in the user session will be saved in the authlogic user_sessions table.
Goto: http://apidock.com/rails/ActiveRecord/SessionStore
For more information
For now you can replace
UserSession.create #user
to
UserSession.create :email => #user.email, :password => #user.password
not a big deal.
But that caught me other way. I forgot that my user got active? == false when created. I've set it to true and session is created.
I ran into this problem today. In my case it ended up being related to CSRF tokens.
We are creating a user and session in our app in response to an OAuth callback. It appears that if the CSRF token is invalid, which would be the case when coming from a third party, authlogic won't create the user session.
Can't verify CSRF token authenticity
The fix was simple:
class Oauth::UserSessionsController < ApplicationController
skip_before_action :verify_authenticity_token, only: :callback
def new
# code removed...
end
def callback
# code removed...
UserSession.create(#user)
redirect_to root_path
end
end