浩文 联系 关于本站 登录 注册
  • 关注新浪微博:
  • 关注微信公众号:

Devise Github Wiki 中文文档

README

commit信息:Remove Heroku anchor link and fix some typos | 提交者:ptcodes | 提交时间:2020-06-16 | 版本:b25492e

Devise Logo

Build Status
Code Climate

Devise是基于Warden的灵活的rails身份认证解决方案。 它:

它由10个模块组成:

目录

<!-- TOC depthFrom:1 depthTo:6 withLinks:1 orderedList:0 -->

资料

Devise wiki

divse WIki有许多关于Devise的附加资源,包括许多“how-to”文章以及常见问题回答。请在完成README之后浏览Wiki:

https://github.com/heartcombo/devise/wiki

Bug报告

如果你发现了Devise的问题,我们也想知道。但是,我们要求你在提交错误报告之前先阅读以下准则:

https://github.com/heartcombo/devise/wiki/Bug-reports

如果你发现了与安全相关的错误,请 要发起github issue。请给 heartcombo@googlegroups.com 发送电子邮件。

StackOverflow和邮件列表

如果你有任何问题、评价或是担忧,请使用stackoverflow而不是GitHub issue:

http://stackoverflow.com/questions/tagged/devise

你仍然可以阅读过时的邮件列表

https://groups.google.com/group/plataformatec-devise

RDocs

你可以在这里看Devise的RDoc格式文档:

http://rubydoc.info/github/heartcombo/devise/master/frames

如果你搭配以前版本的rails来使用devise, 在你安装了gem之后可以在命令行运行"gem server"命令来获取旧的文档。

例子应用

在GitHub上有一些有效的例子应用,它们搭配不同版本的Rails示范了许多devise功能。

扩展

我们的社区已经创建了许多扩展,添加了Devise没有的功能。你可以在这里查看有效扩展列表并且添加你自己的扩展:

https://github.com/heartcombo/devise/wiki/Extensions

贡献

我们希望你想给device做贡献。阅读这篇简短的概览来获取一些如何起步的资料。

https://github.com/heartcombo/devise/wiki/Contributing

如果你通常想给你的功能改变写一些测试。为了运行测试,请进入Devise的顶层水平文件夹,然后运行 bundle installbin/test
Devise可以搭配许多Ruby和rails版本、ActiveRecord和Mongoid ORMs来工作,那意味着你可以搭配一些DEVISE_ORMBUNDLE_GEMFILE的修改来运行测试。

DEVISE_ORM

因为 Devise 同时支持 Mongoid 和 ActiveRecord, 所以我们依赖此变量用来运行每个ORM特定的代码。DEVISE_ORM的默认值是active_record。你可以传递mongoid来运行Mongoid的测试:

DEVISE_ORM=mongoid bin/test

==> Devise.orm = :mongoid

在运行Mongoid测试时,需要在你的系统上有(2.0以上版)的MongoDB服务。

请注意,该命令的输出将显示正在使用的变量值。

BUNDLE_GEMFILE

我们可以使用该变量来告诉bundler它该使用哪个Gemfile文件(来替代当前文件夹下的Gemfile文件)。在[gemfiles]](https://github.com/heartcombo/devise/tree/master/gemfiles) 文件夹里,有我们支持的每个rails版本。当你给我们发送一个获取请求时, it may happen that the test suite breaks on Travis using some of them.如果出现这种状况,你可以使用BUNDLE_GEMFILE变量来模拟相同的环境。
例如,如果在使用Ruby 2.4.2和Rails 4.1时测试代码出问题了,你可以像下面这样做:

rbenv shell 2.4.2 # or rvm use 2.4.2
BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bundle install
BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bin/test

如果测试代码在Mongoid中出错,你也可以一起使用它们:

BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bundle install
BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable DEVISE_ORM=mongoid bin/test

运行测试

Devise使用Mini test 测试框架

bin/test
bin/test test/models/trackable_test.rb

运行指定测试:

bin/test test/models/trackable_test.rb:16

从Rails起步?

如果你正在构建第一个Rails应用,我们建议你 不要 使用Devise。使用Devise依赖对rails框架的正确理解。在这种情况下,我们建议你从头建立一个简单的身份认证系统。这里有一些能帮你起步的资源:

如果你已经理解了rails和身份验证机制,我们向你保证Devise使用起来将非常合适。 :smiley:

起步

Devise 4.0工作在rails 4.1以上。把下面这行添加到你的Gemfile文件中:

gem 'devise'

然后运行bundle install

接下来你需要运行生成器:

$ rails generate devise:install

此时,许多操作说明将出现在console中。遵从这些操作说明,你需要在每个环境中设置Devise的邮件发送者默认URL选项。这里有一个config/environments/development.rb文件的参考配置:

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

生成器将装上一个初始程序,它描述了所有的Devise配置选项。你 一定要 看一看。当你看过之后,你可以使用生成器把device添加到你的任何一个模型中。

你需要使用应用里用户的类名来重置下面命令中的MODEL(它经常是User也可以是Admin)。该命令将创建模型(如果模型还不存在),并且配置它使用Devise的默认模块。生成器还将你的config/routes.rb文件配置为指向Devise的控制器。

$ rails generate devise MODEL

接下来查看MODEL来添加你想添加的附加配置选项,像是confirmable和lockable。如果你添加了一个配置项,请你确保检查了该迁移文件(如果你的ORM支持,则由生成器创建)同时给适当的部分解除注释。例如你在模型中添加了confirmable选项,你需要在迁移文件中解除Confirmable部分的注释。

然后运行rails db:migrate

在改变的Devise的配置选项之后你应该重启你的应用(包括停止spring)。否则你将得到奇怪的错误,例如:用户不能登录和路由帮助方法未定义。

控制器过滤器和帮助方法

device将创建一些在你的控制器和视图里可以使用的帮助方法。为了设置控制器使用用户身份认证,只需要添加以下before_action(假设你的Devise模型是'User'):

before_action :authenticate_user!

对Rails 5来说,请注意,protect_from_forgery不再预置到before_action链中,因此,如果你在protect_from_forgery之前设置authenticate_user,你的请求将产生"Can't verify CSRF token authenticity"的结果。为了解决该问题,请改变你调用它们的顺序,或者使用protect_from_forgery prepend: true

如果你的Devise模型不是User,请使用"_yourmodel"重置"_user"。对下面的指令应用相同的逻辑。

使用下面的帮助方法来验证用户是否登录:

user_signed_in?

下面的帮助方法在当前有登录用户时有效:

current_user

你可以获取当前用户的session:

user_session

在登录用户、confirming the account或者更新密码之后,Devise将寻找一个用来跳转的路由,在你使用:user资源时,如果存在user_root_path路由则将使用它;否则,默认的root_path路由将被使用。这意味着你需要在路由文件中设置你的根路由:

root to: 'home#index'

你也可以重写after_sign_in_path_forafter_sign_out_path_for以定制你的跳转页面。

请注意,例如,如果你的Devise模型被称作Member而不是User,下面的帮助方法将生效:

before_action :authenticate_member!

member_signed_in?

current_member

member_session

配置模型

在你的模型中的Devise方法也可以接受一些选项来配置它们的模块。例如你可以像下面这样设置哈希算法的开销:

devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 13

除了:stretches之外,你可以沿着其他选项定义:pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in选项。了解详情,请参阅初始程序文件,它是上面描述的在你调用"devise:install"生成器时创建的文件。该文件通常位于/config/initializers/devise.rb

健壮参数

Devise 4的Parameter Sanitizer API已更改 :warning:

在定制你的视图时,你或许想往一些form里添加新的属性。Rails 4 把参数安全处理操作从模型移动到了控制器,从而使Devise在控制器中也能处理此问题。

Devise中有三个action,它们可以传递给模型任何参数,因此它们需要被安全操作。它们的名字和默认允许的参数是:

有时你想允许其它参数(the lazy way™),你可以在ApplicationController中使用before action:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
  end
end

以上代码可以添加任何附加字段,这些字段是简单的scalar类型。如果你有一些嵌套属性(例如,你正在使用accepts_nested_attributes_for),你需要给Devise说明这些嵌套属性和它们的类型:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, address_attributes: [:country, :state, :city, :area, :postal_code]])
  end
end

Devise允许完全改变它的默认行为或者通过传递一个块来调用定制的行为:

为了允许简单scalar值的username和email,请使用以下代码

def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_in) do |user_params|
    user_params.permit(:username, :email)
  end
end

如果你有一些复选框,它们展示一些用户可以在注册过程中获取的角色,浏览器会使用数组来发送这些选定的复选框值。数组不是健壮参数功能允许的scalars中的一个类型,因此我们需要像下面这样配置Devise:

def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up) do |user_params|
    user_params.permit({ roles: [] }, :email, :password, :password_confirmation)
  end
end

想要列出允许的scalars,以及如何在嵌套hashes和arrays中声明允许的keys,请参阅

https://github.com/rails/strong_parameters#nested-parameters

如果你有多个Devise模型,你或许想给每个模型设置不同的参数安全检测。这种情况下,我们推荐继承Devise::ParameterSanitizer然后添加你自己的逻辑:

class User::ParameterSanitizer < Devise::ParameterSanitizer
  def initialize(*)
    super
    permit(:sign_up, keys: [:username, :email])
  end
end

并且之后配置你的控制器使用它:

class ApplicationController < ActionController::Base
  protected

  def devise_parameter_sanitizer
    if resource_class == User
      User::ParameterSanitizer.new(User, :user, params)
    else
      super # Use the default one
    end
  end
end

以上的例子重写user允许的参数为:username:email。该non-lazy配置参数方式将在定制控制器中定义以上before过滤器。我们在以下部分详细讲解如何配置和定制控制器。

配置视图

我们创建了Devise以帮你快速开发一个需要身份认证的应用。However, we don't want to be in your way when you need to customize it.

因为Devise是一个引擎,它所有的视图文件被打包在gem中。这些视图帮你起步,但一段时间后你想改变它们。如果发生这种情况,你只需要调用下面的生成器,然后它将拷贝所有的视图文件到你的应用:

$ rails generate devise:views

如果在你的应用中你有不止一个Devise模型(像是UserAdmin),你会注意到Devise对所有的模型使用相同的视图。幸运的是Devise提供了一个简单的方式来定制视图。你需要做的只是在config/initializers/devise.rb文件中设置config.scoped_views = true

这样做之后,你可以有基于角色的视图像是users/sessions/newadmins/sessions/new。如果在scope中没有发现任何视图,Devise将使用devise/sessions/new文件中的默认视图。你也可以使用生成器来生成scoped视图:

$ rails generate devise:views users

如果你只想生成少数的视图,像是只有registerableconfirmable模块的视图,你可以使用-v标记来给生成器传递一个模块列表。

$ rails generate devise:views -v registrations confirmations

配置控制器

如果视图水平的定制不够你用,你可以遵从以下步骤来定制每个控制器:

  1. 使用依赖scope的生成器来创建和定制控制器:

    $ rails generate devise:controllers [scope]
    

    如果你指定users作为scope, 控制器会被创建在 app/controllers/users/文件中。
    然后会话控制器看起来会像下面这样:

    class Users::SessionsController < Devise::SessionsController
      # GET /resource/sign_in
      # def new
      #   super
      # end
      ...
    end
    

    (使用 -c 标记来指定一个控制器,例如: rails generate devise:controllers users -c=sessions

  2. 告诉路由使用该控制器:

    devise_for :users, controllers: { sessions: 'users/sessions' }
    
  3. devise/sessions处拷贝视图到users/sessions处。因为控制器已经被改变,它将不会使用devise/sessions处的默认视图。

  4. 然后修改和扩展你需要的控制器actions。

    你可以完全重写一个控制器action:

    class Users::SessionsController < Devise::SessionsController
      def create
        # custom sign-in code
      end
    end
    

    或者简单地往它里面添加新的行为:

    class Users::SessionsController < Devise::SessionsController
      def create
        super do |resource|
          BackgroundWorker.trigger(resource)
        end
      end
    end
    

    以上代码对于触发后台作业或者在某些操作期间记录事件很有用。

请记着Devise使用闪现消息通知用户是否成功登录。Devise期望你的应用正确调用flash[:notice]flash[:alert]。不要打印整个闪现消息哈希,只打印特定的键。Devise在Flash hash中添加了:timedout键,该键不用于显示。如果你想要打印整个hash请移除该键。

配置路由

Devise也附带默认路由。 如果需要定制它们,应该使用devise_for方法来实现。 它接受几个选项,例如:class_name,:path_prefix等,也包括修改I18n路径名:

devise_for :users, path: 'auth', path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }

请确保查看devise_for 文档 来查看详情。

如果你有深层次定制需求,例如除了"/users/sign_in"之外还想使用"/sign_in",你只需要在路由文件里创建你的正常路由然后把它们包装在devise_scope块之内:

devise_scope :user do
  get 'sign_in', to: 'devise/sessions#new'
end

通过该种方式,当"/sign_in"被请求时Devise会使用:user域。注意,devise_scope在路由器文件中也是别名就像as一样。

请注意:为了使用像current_user这样的帮助方法,你仍需要在你的路由文件中添加devise_for

devise_for :users, skip: :all

I18n

Devise搭配I18n来使用闪现消息,并且使用:notice和:alert闪现消息键。为了定制你的应用,你可以配置你的本地化文件:

en:
  devise:
    sessions:
      signed_in: 'Signed in successfully.'

基于路由文件中你配置使用的单数名字,你可以创建不同的消息:

en:
  devise:
    sessions:
      user:
        signed_in: 'Welcome user, you are signed in.'
      admin:
        signed_in: 'Hello admin!'

Devise邮件程序使用简单的策略来创建主题消息:

en:
  devise:
    mailer:
      confirmation_instructions:
        subject: 'Hello everybody!'
        user_subject: 'Hello User! Please confirm your email'
      reset_password_instructions:
        subject: 'Reset instructions'

看下我们的本地化文件来查看所有有效的消息。你或许会对我们wiki中提供的众多翻译之一感兴趣:

https://github.com/heartcombo/devise/wiki/I18n

注意事项:Devise控制器继承ApplicationController。如果你的应用使用多种本地化,你应该确保在ApplicationController中设置I18n.locale 。

测试帮助方法

Devise给控制器测试和集成测试提供了一些测试帮助方法。为了使用它们你应该分别包含它们到你的测试cases/specs中。

控制器测试

控制器测试依赖你在测试用例中包含Devise::Test::IntegrationHelpers,或者是它的超类ActionController::TestCase。对于Rails 5之前的版本,要包含Devise::Test::ControllerHelpers,因为控制器测试超类被改变为ActionDispatch::IntegrationTest(了解详情,请查看集成测试部分)。

class PostsControllerTest < ActionController::TestCase
  include Devise::Test::IntegrationHelpers # Rails >= 5
end
class PostsControllerTest < ActionController::TestCase
  include Devise::Test::ControllerHelpers # Rails < 5
end

如果你使用RSpec,你可以把下面代码放入spec/support/devise.rb 或者 spec/spec_helper.rb文件中(如果你使用rspec-rails,它是spec/rails_helper.rb)中:

RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::ControllerHelpers, type: :view
end

只要保证包含代码被放在require 'rspec/rails'指令 之后

现在你就可以在控制器测试中使用sign_insign_out方法了:

sign_in @user
sign_in @user, scope: :admin

如果你正在测试Devise的内部控制器或者一个继承自Devise的控制器,你需要告诉Devise应该在请求前使用哪个路径。这是必要的,因为Devise需要从路由中得到该信息,但是因为控制器测试不通过路由传递该信息,所以该信息需要被明确说明。例如,你正在测试用户scope,只需这样做:

test 'GET new' do
  # 通过env设置Devise scope的模拟路由
  @request.env['devise.mapping'] = Devise.mappings[:user]

  # 使用sign_in帮助方法 来登录固件`User`。
  sign_in users(:alice)

  get :new

  # 断言一些事情
end

整合测试

通过包含`Devise::Test::IntegrationHelpers模块,集成测试帮助方法将会生效。

class PostsTests < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers
end

现在你可以在你的集成测试中使用下面的sign_insign_out方法:

sign_in users(:bob)
sign_in users(:bob), scope: :admin

sign_out :user

RSpec用户可以在他们的:feature specs中包含IntegrationHelpers模块。

RSpec.configure do |config|
  config.include Devise::Test::IntegrationHelpers, type: :feature
end

不像控制器测试,集成测试不需要给它提供devise.mappingenv值,因为使用你测试中执行的路由可以推断出该路径。

在该Wiki中你可以阅读更多关于Rails 3 - Rails 4的RSpec控制器测试:

OmniAuth

为了使用其它服务商的身份验证信息,Devise创建了开箱即用的OmniAuth支持。想要使用它,只需要在config/initializers/devise.rb文件中指定你的OmniAuth配置:

config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'

在该Wiki中你可以查阅更多关于OmniAuth支持的信息:

配置多个模型

Devise让你可以设置许多你想有的Devise模型。如果你想有一个Admin模型,只是用来提供身份验证和超时功能,并且有额外的User模型,只需运行:

# 创建依赖字段的迁移
create_table :admins do |t|
  t.string :email
  t.string :encrypted_password
  t.timestamps null: false
end

# 在你的Admin模型文件中加入
devise :database_authenticatable, :timeoutable

# 在你的路由文件中加入
devise_for :admins

# 在你的保护控制器中加入
before_action :authenticate_admin!

# 在你的控制器和视图中加入
admin_signed_in?
current_admin
admin_session

或者,你只需运行Devise生成器。

请注意这些模型将有完全不同的路由。它们 不可以不能 为了登录账户、退出账户等操作分享相同的控制器。在这种情况下,如果你想给不同的角色分享一些同样的动作,我们推荐你使用基于角色的方法,提供一个角色列,或者用专业的权限gem进行授权。

ActiveJob集成

如果你使用Rails 4.2 和 ActiveJob通过后台队列来投递ActionMailer信息,在你的模型中复写send_devise_notification方法,这样你可以使用队列来发送Devise电子邮件。

def send_devise_notification(notification, *args)
  devise_mailer.send(notification, self, *args).deliver_later
end

重设密码token和rails日志记录

如果你开启了Recoverable模块,注意一个密码重设token被盗可以让攻击者登陆你的应用。Devise尽力生成随机的、安全的tokens,并且在数据库中储存token摘要,不储存纯文本。Rails中的默认日志记录行为会把纯文本token泄漏到日志文件中:

  1. 对于DEBUG日志记录水平,Action Mailer日志会记录完整的发送的电子邮件内容。在电子邮件中投递给用户的密码重设token将会被泄露。
  2. 在INFO水平下Active Job会记录传给每一个排队作业的所有参数。如果你配置Devise在发送密码重设电子邮件时使用 deliver_later,密码重设tokens将会被泄露。

Rails 默认把生产日志记录水平设为DEBUG。 如果你希望阻止tokens 被泄露到你的日志文件中,请考虑把你的生产日志水平设为WARN 。在config/environments/production.rb文件中:

config.log_level = :warn

其它的ORMs

Devise (默认)支持ActiveRecord和Mongoid。对于选择其它ORM的情况,只需在初始化文件中请求它。

Rails API模式

Rails 5+内置了API 模式,它优化Rails (只)使用API。从某种意义上讲,Devise能够处理以这种方式构建的应用程序,而无需进行其它修改,它不应该引发异常。但是一些issues依然在development/testing环境下被触发,我们仍然不太了解整体的兼容性程度。(了解详情,请查看issue #4947

支持认证策略

API-only应用不支持使用cookie的浏览器模式认证,那是devise的默认方式。但是,在这种情况下,devise仍提供开箱即用的http_authenticatable策略身份认证,该身份认证使用HTTP Basic Auth并在每个请求上验证用户。(了解详情,请查看该Wiki文章How To: Use HTTP Basic Authentication

devise默认关闭HTTP Auth,因此如果使用它,需要在初始化文件中开启数据库策略:

config.http_authenticatable = [:database]

该约束不限制在你的应用里和在devise的gem-based扩展里实现定制的warden 策略。
token-based身份认证是一个公认的API应用身份认证策略。关于扩展devise支持该种身份认证和其他的身份认证的更多信息,请查看这篇Wiki文章简单Token身份认证例子和替代方案,或者该篇关于定制Devise身份验证方法的博客

测试中

API模式改变了中间件栈的顺序,所以会造成Devise::Test::IntegrationHelpers问题。该问题通常在使用集成测试帮助方法时显现为undefined method `[]=' for nil:NilClass 错误,例如#sign_in。解决方法很简单,添加下面的代码到测试文件中来重新排列中间件:

Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies
Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Session::CookieStore

关于该问题的深层次理解,请回顾该issue

另外需要注意的是,离开了视图支持,此时,那些来自于Confirmable, Recoverable 和 Lockable的邮件流不能被直接支持。

附加资料

Warden

Devise基于Warden,它是一个被Daniel Neighman创建的通用身份验证框架。我们鼓励你在下面地址里阅读更多的Warden信息:

https://github.com/wardencommunity/warden

贡献者们

我们有一长串有价值的贡献者。在这里查看他们:

https://github.com/heartcombo/devise/graphs/contributors

授权

MIT License. Copyright 2020 Rafael França, Leonardo Tegon, Carlos Antônio da Silva. Copyright 2009-2019 Plataformatec.

Devise logo的许可证是Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.