devise limit one session per user at a time
A user can only be signed in a single session at a time. This means if he logged in to computer A then afterwards he logged in to computer B, then computer A times out. The original question was solved in http://stackoverflow.com/questions/7068919/devise-limit-one-session-per-user-at-a-time
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base protect_from_forgery before_filter :authenticate_user!, :check_concurrent_session, :store_location ... def check_concurrent_session if is_already_logged_in? sign_out_and_redirect(current_user) end end def is_already_logged_in? current_user && !(session[:token] == current_user.login_token) end def after_sign_out_path_for(resource) loggedout_path end end |
app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController skip_before_filter :check_concurrent_session def create super set_login_token end private def set_login_token token = Devise.friendly_token session[:token] = token current_user.login_token = token current_user.save end end |
app/controllers/static_controller.rb
class StaticController < ApplicationController skip_before_filter :authenticate_user! end |
app/views/sessions/new.html.erb
<div id="application"> <nav id="secondary"> <ul> <li class="current"><%= link_to "Log In", new_user_session_path %></li> <%- if devise_mapping.recoverable? && controller_name != 'passwords' %> <li><%= link_to "Forgot Password", new_password_path(resource_name) %></li> <% end -%> </ul> </nav> <section id="content"> <%= semantic_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %> <section> <%= f.input :username %> </section> <section> <%= f.input :password %> </section> <%= f.buttons do %> <%= f.commit_button :label => "Login", :button_html => { :class => "button primary submit"} %> <% end %> <br/> <% end %> <%= render :partial => 'layouts/devise/devise_error_messages' %> </section> </div> |
app/views/static/loggedout.html.erb
<section id="content"> <h1>Logged Out</h1> <hr/> <p>This is not an error page but an indication that you have lost your session.</p> <p><b>So why are you here?</b></p> <ul> <li>- You have successfully logged out after clicking the "Logout" button.</li> <li>- You logged in to another machine so we logged this session out. We don't want to have multiple logins everywhere for security purposes.</li> <li>- You have been inactive for a while, we logged this session out.</li> </ul> <p><b><%= link_to "Login", new_user_session_path, :class => "button" %></b></p> </section> |
config/routes.rb
devise_for :users, :controllers => { :sessions => "sessions" } .. match "loggedout" => "static#loggedout" end |
db/migrate/20120223022102_add_login_token_to_users.rb
class AddLoginTokenToUsers < ActiveRecord::Migration def self.up PgTools.restore_default_search_path change_table "users" do |t| t.string "login_token" end end def self.down PgTools.restore_default_search_path change_table "users" do |t| t.remove "login_token" end end end |