设计 - 如果同一用户从其他浏览器/计算机登录,则会使用户会话无效

Kal*_*ani 5 devise ruby-on-rails-3

我有一个场景,我需要限制用户一次只有一个活动会话.我是一个rails3应用程序,并使用设计进行身份验证.我有兴趣只保留最新的用户会话.即,如果用户登录时有另一个会话对同一用户名有效,我想停用旧会话并允许最近的会话.在设计方面,是否有办法获取用户会话并使其无效?

dex*_*ter 15

您可以通过在数据库中存储特定于该用户的唯一标记来跟踪特定用户的会话.

创建迁移以添加用于存储令牌的字段.我假设设计模型是用户.

class AddSignInTokenToUsers < ActiveRecord::Migration
  def change
    add_column :users, :current_sign_in_token, :string
  end
end
Run Code Online (Sandbox Code Playgroud)

将以下代码添加到 application_controller.rb

class ApplicationController < ActionController::Base
  before_filter :invalidate_simultaneous_user_session, :unless => Proc.new {|c| c.controller_name == 'sessions' and c.action_name == 'create' }

  def invalidate_simultaneous_user_session
    sign_out_and_redirect(current_user) if current_user && session[:sign_in_token] != current_user.current_sign_in_token
  end

  def sign_in(resource_or_scope, *args)
    super
    token = Devise.friendly_token
    current_user.update_attribute :current_sign_in_token, token
    session[:sign_in_token] = token
  end
end
Run Code Online (Sandbox Code Playgroud)

sign_in(resource_or_scope, *args) 是一个设计钩子,每次用户登录时都会调用它.

invalidate_simultaneous_user_session 如果当前用户的另一个实例登录,则将注销当前用户.这将确保在任何时刻只有一个会话对用户是活动的.

invalidate_simultaneous_user_session应跳过过滤器,以便用户登录操作更新新登录的用户令牌.我不满意使用Proc来根据控制器名称和操作跳过过滤器.如果你已经覆盖了设计sessions_controller,那么skip_before_filter :check_simultaneous_user_session在控制器中包含你可以摆脱Proc!

希望这可以帮助..