最近项目中使用了
Devise 来做用户验证,不像以前只有简单的用户登录。这次开发涉及到不同角色用户登录,不同使用环境登录(电脑端+手机端),并且可以同时使用手机号码,特定商户号登录等,需要修正的地方有点多,特地记录下来,供下次使用。
1、不同角色用户登录。
直接使用一个 user 表作为基础,添加记录角色的字段即可
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
使用不同的角色类来继承这个表,并设置角色字段的值:
class BusinessUser < User
default_scope { where(role: 1) }
end
class Admin < User
default_scope { where(role: 0) }
end
在Routes文件中添加对不同角色的登录routes:
devise_for :admin
devise_for :business_user, controllers: {
sessions: 'business_user/sessions',
passwords: 'business_user/passwords'
}
在 application_controller.rb 文件添加这两个类的 Group
devise_group :user, contains: [ :business_user, :admin]
2、同时可以使用手机号码,邮件和特定商户号登录。
在
User 类中显示设置数据库查询的函数,并添加一个虚拟字段
Login 用来设置用户传入的内容:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:authentication_keys => [:login]
attr_accessor :login
def login=(login)
@login = login
end
def login
@login || self.business_num || self.phone || self.email
end
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions.to_h).where(["business_num = :value OR phone = :value OR email = :value", { :value => login }]).first
else
where(conditions.to_h).first
end
end
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["business_num = :value OR email = :value", { :value => login }]).first
else
if conditions[:business_num].nil?
where(conditions).first
else
where(business_num: conditions[:business_num]).first
end
end
end
end
在 application_controller.rb 文件中修正 Devise 的 strong parameters:
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:business_num, :phone, :email, :password, :password_confirmation, :remember_me)
}
devise_parameter_sanitizer.for(:sign_in) { |u|
u.permit(:login, :business_num, :phone, :email, :password, :remember_me)
}
devise_parameter_sanitizer.for(:account_update) { |u|
u.permit(:business_num, :phone, :email, :password, :password_confirmation, :current_password, :reset_password_token)
}
end
将原有的 Login Form 中的 Email 相关的内容替换为以下部分:
<%= f.text_field :login, :autofocus => true, :class => "loginInput", %>
3、设置电脑端登录和手机端登录失败后跳转到不同的页面。
主要是需要设置登录失败后,需要跳转到不同的页面,这个地方需要设置
warden 。
在 devise.rb 文件中添加代码,自定义用户登录失败后的跳转链接
config.warden do |manager|
manager.failure_app = CustomFailure
end
在 lib 文件中新建文件 custom_failure.rb 内容如下:
class CustomFailure < Devise::FailureApp
def redirect_url
if warden_options[:scope] == :business_user
session[:is_mobile] == true ? mobile_login_url : new_business_user_session_url
else
new_admin_session_path
end
end
# You need to override respond to eliminate recall
def respond
if http_auth?
http_auth
else
redirect
end
end
end
同时需要在 application.rb 中添加代码加载这个文件:
config.autoload_paths << Rails.root.join('lib')
参考资料: