devise是基于Warden的rails灵活的身份验证方案:
- 添加gem,在Gemfile中添加
gem 'devise'
#添加后命令:bundle install
- 运行生成器
$ rails generate devise:install
- 接下来在config/environments/development.rb中配置
config.action_mailer.default_url_options = { host: ‘localhost’, port: 3000 }
- 创建一个用户模型:
$ rails generate devise MODEL
这里的MODEL就是模型的名字,USER,ADMIN,ADMIN_USER
然后运行 :$ rails db:migrate
如果你想对那个方法进行登录的验证的话,就在Controller类上添加:
before_action :authenticate_user!
_user! 就是上边MODEL的名称
如果你在application_controller.rb中添加以上操作,就是对所有的方法都要进行登录验证
这里遇到一个坑:不要自己手动在数据库中添加数据,会报错,因为密码添加的方式不同,所以我们可以在devise生成的注册中进行创建用户
登录之后,devise会有默认跳转到root,如果想自定义跳转,需要覆盖after_sign_in_path_for和after_sign_out_path_for来自定义跳转回调
- 修改视图
$ rails g devise:views
在view下生成devise文件,里边包含登录,注册,修改等视图可做修改
- devise默认创建的帮助方法
- user_signed_in? //判断用户是否登录
- current_user //获取当前登录用户
- user_session //可以访问对应的session
此处的user对应创建模型的名字
- devise除了用emails登录外,也可以自定义登录字段
rails generate migration add_username_to_users username:string
此处的users对应模型的名字
然后运行 rails db:migrate
- 增加字段后,在config/initializers/devise.rb中配置登录验证的字段
config.authentication_keys = [:username]
config.case_insensitive_keys = [:username]
config.strip_whitespace_keys = [:username]
第一个配置为登录的字段
第二个配置为不区分大小写
第三个配置为删除后边的空格
- 修改完字段后,对登录的view进行修改,加入username的input
- 修改完之后,接下来需要重写一个方法,用来配置登录和注册所允许的参数,将此方法写在application_controller.rb中
- 修改完之后,接下来需要重写一个方法,用来配置登录和注册所允许的参数,将此方法写在application_controller.rb中
def configure_permitted_parametersod_name
devise_parameter_sanitizer.permit(:sign_in) {|u| u.permit(:email, :username)}
devise_parameter_sanitizer.permit(:sign_up) {|u|
u.permit(:email, :username, :password, :password_confirmation)}
end
在application_controller.rb还需要配置
before_action :configure_permitted_parametersod_name, if: :devise_controller?
如果没有配置这个,在注册的时候,会出现邮箱验证不通过的BUG
- 为了使得用户名和邮箱都可以登录
需要在user模型里加入一个虚拟属性:attr_accessor :signin
然后在/config/initializers/devise.rb中修改验证参数
config.authentication_keys = [ :signin ]
- 修改了验证参数之后,需要去模型里面重写登录devise会使用到的方法,在user.rb里面重写self.find_for_database_authentication方法
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if signin = conditions.delete(:signin)
where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => signin.downcase }]).first
elsif conditions.has_key?(:username) || conditions.has_key?(:email)
where(conditions.to_h).first
end
end
- 在模型里定义完方法之后,需要将application_controller.rb中那个允许参数的方法重写
def configure_permitted_parametersod_name
devise_parameter_sanitizer.permit(:sign_in) {|u| u.permit(:signin, :password, :remember_me)}
devise_parameter_sanitizer.permit(:sign_up) {|u|
u.permit(:email, :username, :password, :password_confirmation)}
end
- 去登录视图中,将username的input改成signin的input,这样一来,用用户名和邮箱都可以实现登录功能