如何在 Rails 7 应用程序中使用 Devise 设置用户身份验证

作者选择了 Girls Who Code以作为 Write for Donations计划的一部分获得捐款。

介绍

Devise宝石是 Ruby on Rails应用程序的身份验证解决方案;它有助于您在项目中设置生产准备的用户身份验证,而无需自行完成所有操作。

Devise 使用户身份验证变得简单,就像初始化宝石并创建具有所需功能的用户模型一样。如果您要从头开始构建用户身份验证,您将不得不为您想要的所有功能编写代码和测试,并在处理会话、存储 Cookie 和保持数据安全时处理所有边缘案例。

在本教程中,您将使用 Rails 创建一个最小的Web应用程序并安装 Devise,这将允许用户创建帐户,登录和退出他们的帐户。

前提条件

要完成本教程,您将需要:

  • 铁路上的Ruby的地方发展环境。 对于Linux,您可以跟踪我们的教程[如何在Ubuntu 20.04上的rvm'在铁路上安装Ruby (https://andsky.com/tech/tutorials/how-to-install-ruby-on-rails-with-rvm-on-ubuntu-20-04),或者使用rvm'产品docs用于[总计在Mac或Windows上] (https://rvm.io/rvm/install#any-other-system)。 也可以指: [Ruby project docs] (https://www.ruby-lang.org/en/documentation/installation/) 直接将Ruby安装在您的系统中. 要安装"铁路宝石",可以使用"铁路官方文件"(https://guides.rubyonrails.org/getting_started.html). Devise 宝石需要 Ruby 版本 2.1.0 或 以上;此教程曾使用 Ruby 版本 3. 0.2 和 Rails 版本 7.0.3. (_ ( )* 节点Js安装在您的机器上。 少数铁路功能,如"资产管道",依赖于JavaScript runtime. Node.js提供这个功能. 对于Ubuntu,如如何在Ubuntu 20.04上安装Node.js备选案文2所解释的那样,使用官方的PPA安装Node.js. 对于Mac OS,请遵循我们的指南[如何在MacOS上安装节点.js并创建一个本地开发环境] (https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos).
  • 与Ruby和Ruby在铁路上的框架熟悉. 你可以从我们的系列集装箱上的信封中检查出第一批的教程,也可以使用官方的信封指南. (- )

步骤 1 – 创建一个新的 Rails 应用程序

在此步骤中,您将创建一个新的 Rails 应用程序,并在您的机器上本地运行。

从终端执行下列命令:

1rails new blog

rails new 命令将创建一个新的 Rails 项目在blog目录下,其中包括一系列生成的文件和文件夹。其中一个是 Gemfile,其中包含该项目的依赖性。

<$>[注] 注: 如果您收到一个错误,说找不到宝石,您可以通过更改到您的项目目录(cd 博客)并运行组装安装,这将安装您的Gemfile中列出的所有宝石。

您可以在您最喜欢的文本编辑器中打开此目录,或使用终端导航:

1cd blog

要启动 Rails 应用程序,请从项目目录中使用rails server命令启动开发服务器:

1bundle exec rails server

此命令将启动 Rails 开发服务器。在您的浏览器中打开 http://localhost:3000 以访问 Rails 欢迎页面。 Rails 使用 3000 端口来运行应用程序,如果您没有提供替代端口号。

<$>[注] *_注:_添加 bundle exec 到您的命令在当前包的背景下执行它. 这意味着只会使用项目特定的 Gemfile 和其中定义的宝石版本。

您现在已经初始化了一个新的 Rails 应用程序,您将在后一步中添加用户身份验证。在下一步中,您将替换 Rails 提供的默认主页,以自定义定位页,这将使您在添加 Devise 后更容易导航样本应用程序。

步骤二:创建一个登陆页

现在你有一个基本的 Rails 应用程序,你将取代 Rails 提供的默认页面为你自己的定位页面. 一个自定义定位页面将使它更容易显示用户链接在应用程序的根 URL 登录和登录。

要创建您的定位页面,您需要执行以下操作:

  • 将路线添加到 config/routes.rb 文件中
  • 创建一个 `HomeController' 来处理该路线的请求
  • 创建一个视图文件,当您击中路线时将其渲染

您将首先将根路径添加到您创建项目时生成的 routes.rb 文件中。

使用nano或您最喜欢的文本编辑器,打开先前生成的config/routes.rb文件:

1nano config/routes.rb

添加突出的线条:

1[label config/routes.rb]
2Rails.application.routes.draw do
3  root to: "home#index" 
4end

root to: 定义哪个控制器操作将处理到根路径的请求 - 在这种情况下,路径将是 http://localhost:3000,这是 Rails 应用程序的默认端口。 该路径的请求将由 home 控制器中的 index 操作处理。 此文件现在不存在,所以您将创建 app/controllers/home_controller.rb 文件。

使用nano,按CTRL+X来退出,按Y来保存,按ENTER来确认文件名并关闭文件。

接下来,创建app/controllers/home_controller.rb文件,并添加以下行:

1[label app/controllers/home_controller.rb]
2class HomeController < ApplicationController
3  def index
4    render
5  end
6end

这是一个基本的HomeController,有一个索引方法,它可以做一件事:将与控制器操作相关的视图文件渲染。

在这种情况下,视图文件将是app/views/home/index.html.erb文件,您需要在app/views目录中创建此文件以及home目录。

保存并关闭Home控制器文件。

接下来,在app/views目录中创建Home目录:

1mkdir app/views/home/

目录将包含特定 Rails 控制器的所有视图。

然后,创建app/views/home/index.html.erb文件,并添加以下行:

1[label app/views/home/index.html.erb]
2<h1>Hello DigitalOcean!</h1>

「app/views/home/index.html.erb」是指「Home」控制器的「index」操作要渲染的 _view 文件。 这是一个 HTML 文件,您可以嵌入 Ruby 代码。 当启动特定控制器操作的路线时,该视图文件会在用户的浏览器中渲染。

保存并关闭您的文件。

要查看根 URL 中的更改,请在浏览器中打开 http://localhost:3000 (或者如果已经打开了,请刷新页面)。

The home page of the application, rendering the index.html.erb file

如果需要,您可以进一步定制此页面,但这就是本教程所需的全部。

现在你有一个简单的 Rails 应用程序,拥有自己的定位页面,你将使用 Devise 宝石添加用户身份验证。

步骤 3 – 安装和配置 Devise

在此步骤中,您将在您的 Rails 应用程序中安装和配置 Devise,以便您可以使用与宝石附带的方法和助手。您将使用方法 user_signed_in? 来检查浏览器中存储的任何登录用户的会话信息。您还将使用 current_user 助手来获取当前登录的帐户的详细信息。 两种方法都嵌入到 Devise 中,您可以直接在您的应用程序中使用它们而无需编写额外的代码。 您可以从 [Devise 项目的 GitHub 页面] 了解更多有关这些助手的方法。

安装 Devise 的第一步是将宝石添加到您的 Gemfile 中,其中包含有关运行 Ruby 项目所需的所有依赖性信息。

但是,在对 Gemfile 进行更改之前,请通过在运行的终端按CTRL+C来阻止您在最后一步中启动的开发服务器。

然后,打开您的 Gemfile 进行编辑. 要添加 Devise 宝石,向文件的末尾添加突出的行,但不在开发测试组之外:

 1[label Gemfile]
 2
 3# ...
 4
 5# Reduces boot times through caching; required in config/boot.rb
 6gem "bootsnap", require: false
 7
 8# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
 9# gem "image_processing", "~> 1.2"
10
11gem "devise" 
12
13group :development, :test do
14  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
15  gem "debug", platforms: %i[ mri mingw x64_mingw ]
16end
17
18# ...

保存并关闭您的文件。

接下来,您将通过在终端中运行bundle install命令来安装新增的宝石。

1bundle install

此命令将在您的项目中安装 Devise 宝石,这将允许您使用devise命令与rails命令行实用程序并配置身份验证。

要在您的项目中设置 Devise,请运行生成器命令:

1bundle exec rails g devise:install

上面的命令中的g旗代表生成,用于调用 Rails 发电机。 发电机将创建可以作为起点的文件。 您可以阅读 Rails 指南 有关 Rails 发电机的更多信息。

此前的命令会生成多个文件,包括初始化文件和 Devise 的 i18n local 文件. 下面详细解释的初始化文件用于配置 Devise,当您首次启动应用程序时。

此时,某些指令也将在终端上打印,如下:

 1[secondary_label Output]
 2===============================================================================
 3
 4Depending on your application's configuration some manual setup may be required:
 5
 6  1. Ensure you have defined default url options in your environments files. Here
 7     is an example of default_url_options appropriate for a development environment
 8     in config/environments/development.rb:
 9
10       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
11
12     In production, :host should be set to the actual host of your application.
13
14     * Required for all applications. *
15
16  2. Ensure you have defined root_url to *something* in your config/routes.rb.
17     For example:
18
19       root to: "home#index"
20
21     * Not required for API-only Applications *
22
23  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
24     For example:
25
26       <p class="notice"><%= notice %></p>
27       <p class="alert"><%= alert %></p>
28
29     * Not required for API-only Applications *
30
31  4. You can copy Devise views (for customization) to your app by running:
32
33       rails g devise:views
34
35     * Not required *
36
37===============================================================================

虽然本教程不需要手动设置,但您将在此步骤晚些时候为通知警告添加闪存消息。

您已完成安装 Devise. 接下来,您需要在刚刚生成的 Devise initializer 文件中配置一些东西。

当你运行devise:install命令时,你生成了config/initializers/devise.rb,这是 Devise 的初始化文件。 每次你启动 Rails 应用程序时,Rails 将加载所有宝石和插件,然后加载所有初始化文件。 您可以从这些初始化文件中配置应用程序的不同部分的特定设置。 所有这些初始化器都位于config/initializers/目录中,这也是 Devise 宝石创建其初始化器的地方。

在文件中,找到Devise.setup块,并添加以下突出的行(Devise.setup`块内可能有其他代码块,但你可以忽略这些):

1[label config/initializers/devise.rb]
2Devise.setup do |config|
3  # ...
4
5  config.navigational_formats = ['*/*', :html, :turbo_stream]
6
7  # ...
8end

此行添加了turbo_stream作为导航格式。Turbo Streams 是 Turbo的一部分,它允许您发送服务器渲染的 HTML 和渲染页面,而不使用大量的 JavaScript。

保存并关闭文件。

接下来,您还会添加在以前打印的指令中突出显示的通知和警报闪存消息。警报通知标签是用户界面中出现错误密码等消息的地方。您可以随时在应用程序中实施自定义警报消息(例如,如果您使用Axios拦截器与React作为您的前端),但对于本教程,您将完成最低限度的Devise设置。

打开app/views/layouts/application.html.erb进行编辑,在身体标签内添加通知警告信息的标签,直接在<%= yield %>上方:

1[label app/views/layouts/application.html.erb]
2...
3<body>
4  <p class="notice"><%= notice %></p> 
5  <p class="alert"><%= alert %></p> 
6  <%= yield %>
7</body>

当视图在浏览器中渲染时, <%= yield %>将被视图文件中的内容取代。

保存并关闭您的文件。

在此步骤中,您已在项目中安装并配置 Devise. 在下一步中,您将使用 Devise 创建应用程序的用户模型,并设置用户身份验证。

步骤 4 – 使用 Devise 创建用户模型

您现在已经准备好使用 Devise 生成用户模型,这将创建必要的模型文件,并生成一个迁移,您可以运行以在您的应用程序中创建一个用户表。

在此步骤中,您将生成用户模型,检查默认配置,然后运行迁移以更新数据库。

由于 Rails 是一个 models-view-controller (MVC) 框架,每个数据库表都有一个类,可以用来处理表中的数据。在这种情况下,如果您创建一个用户表,您可以使用用户模型来执行诸如User.firstUser.find_by_email([email protected])这样的操作。

要创建 Devise 用户,请运行以下生成器命令:

1bundle exec rails g devise user

以下输出将打印到屏幕上:

1[secondary_label Output]
2invoke active_record
3create db/migrate/20220908152949_devise_create_users.rb
4create app/models/user.rb
5invoke test_unit
6create test/models/user_test.rb
7create test/fixtures/users.yml
8insert app/models/user.rb
9route devise_for :users

输出显示 Devise 生成了多个文件,创建了测试,并添加了路线。第一个文件, db/migrate/20220908152949_devise_create_users.rb,是一个迁移文件,用于在您的数据库中创建用户表。一个 Rails 迁移文件描述了需要在数据库中进行的更改。每个迁移的文件名将包含一个时刻印,以便 Rails 知道以何种顺序进行这些更改。

Devise 还创建了用户模型文件 (app/models/user.rb),并对其进行了测试。输出的最后一行表示已添加路线到现有的 config/routes.rb 文件。

在运行迁移文件并在数据库中创建用户表之前,让我们审查这些生成的文件,这将有助于您了解 Devise 生成的配置,以便您知道在运行迁移时会发生什么。

首先,打开迁移文件(db/migrate/20220908152949_devise_create_users.rb)以查看默认代码:

 1[label db/migrate/20220908152949_devise_create_users.rb]
 2# frozen_string_literal: true
 3
 4class DeviseCreateUsers < ActiveRecord::Migration[7.0]
 5  def change
 6    create_table :users do |t|
 7      ## Database authenticatable
 8      t.string :email, null: false, default: ""
 9      t.string :encrypted_password, null: false, default: ""
10
11      ## Recoverable
12      t.string   :reset_password_token
13      t.datetime :reset_password_sent_at
14
15      ## Rememberable
16      t.datetime :remember_created_at
17
18      ## Trackable
19      # t.integer  :sign_in_count, default: 0, null: false
20      # t.datetime :current_sign_in_at
21      # t.datetime :last_sign_in_at
22      # t.string   :current_sign_in_ip
23      # t.string   :last_sign_in_ip
24
25      ## Confirmable
26      # t.string   :confirmation_token
27      # t.datetime :confirmed_at
28      # t.datetime :confirmation_sent_at
29      # t.string   :unconfirmed_email # Only if using reconfirmable

Devise 包含许多有用的选项,如密码重置令牌和发送最后一个令牌的时间等。

由于您不需要进行任何更改,请关闭迁移文件。

Devise 还生成了用户模型文件,这将在app/models/目录中找到。

打开app/models/user.rb模型文件,查看默认代码:

1[label blog/app/models/user.rb]
2class User < ApplicationRecord
3# Include default devise modules. Others available are:
4# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
5devise :database_authenticatable, :registerable,
6       :recoverable, :rememberable, :validatable
7end

Devise 已添加了一些选项来配置用户模型的工作方式. 基本模块(‘database_authenticatable’、‘registerable’、‘recoverable’、‘rememberable’ 和 ‘validable’)已经包括在内。

这就是基本模块所做的:

  • database_authenticatable:用户可以使用登录和密码字段进行身份验证。他们的加密密密码将存储在您的数据库中
  • 可注册:用户可以自己注册并编辑或删除他们的帐户
  • 可恢复:用户可以重置密码并恢复他们的帐户,如果他们忘记了他们的身份验证
  • 可记忆:此模块通过将信息保存到浏览器cookie中来记住用户的会话
  • 可验证:此模块为用户的电子邮件和密码字段提供了验证。

这些基本模块包含在您刚刚生成的用户模型中,您可以在 Devise GitHub 存储库中找到配备 Devise 的完整模块列表。

您不需要做出任何更改,因此关闭用户模型文件。

另一個更新是,「config/routes.rb」檔案已被修改為「用戶」的「devise_for」行:

1Rails.application.routes.draw do
2  devise_for :users
3
4  root "home#index"
5end

这是一个有用的方法,它定义了与用户身份验证相关的所有必要路径,如 /users/sign_in, /users/sign_out/users/password/new. Devise 为您处理所有这些事情,甚至保持路径文件清洁。

您不需要在这里进行任何更改,因此关闭config/routes.rb文件。

要了解应用程序中定义的路径,您可以通过运行以下命令列出它们:

1bundle exec rails routes

此命令打印了所有应用程序路径和这些路径正在处理的控制器. 在身份验证的情况下,所有这些路径都是由 Devise 创建的,您不必手动添加它们。

输出将是漫长的,但这里有一段描述一些路线的片段:

PrefixVerbURI PatternController#Action
new_user_sessionGET/users/sign_in(.:format)devise/sessions#new
user_sessionPOST/users/sign_in(.:format)devise/sessions#create
destroy_user_sessionDELETE/users/sign_out(.:format)devise/sessions#destroy
new_user_passwordGET/users/password/new(.:format)devise/passwords#new
edit_user_passwordGET/users/password/edit(.:format)devise/passwords#edit
user_passwordPATCH/users/password(.:format)devise/passwords#update
PUT/users/password(.:format)devise/passwords#update
POST/users/password(.:format)devise/passwords#create
cancel_user_registrationGET/users/cancel(.:format)devise/registrations#cancel

输出中列出的路线是 Devise 添加的路线,当您在您的路线文件中添加devise_for :users行时。

现在您已经审查了 Devise 生成的文件和配置,您可以使用以下命令运行您在此步骤开始时生成的迁移:

1bundle exec rails db:migrate

上面的命令将对您的数据库中的每个迁移文件进行所有更改. 这些更改需要一个接一个地进行,就像它们在文件中定义一样。

输出如下将打印到屏幕上:

1[secondary_label Output]
2== 20220908152949 DeviseCreateUsers: migrating ================================
3-- create_table(:users)
4 -> 0.0040s
5-- add_index(:users, :email, {:unique=>true})
6 -> 0.0012s
7-- add_index(:users, :reset_password_token, {:unique=>true})
8 -> 0.0011s
9== 20220908152949 DeviseCreateUsers: migrated (0.0074s) =======================

一旦迁移完成,您的数据库将设置,您已经完成了您在项目中设置用户身份验证所需的一切。

在此时刻,重新启动您的 Rails 服务器:

1bundle exec rails server

之前提到的 Initializer 文件只在 Rails 启动时加载,您需要重新启动服务器,这样 Rails 就可以加载新的 Devise Initializer 文件,并为用户身份验证设置一切工作。

在您的浏览器中,点击http://localhost:3000/users/sign_up,在那里您将找到一个注册表格来创建一个帐户,通过输入电子邮件和密码。

The signup page generated by Devise

要测试身份验证,请输入测试电子邮件,如[email protected]和密码。

一旦您登录,您将被重定向到 root 页面,其中显示了 **Hello DigitalOcean!**以及一个消息,称您已成功登录,如下:

Screencapture showing the landing page the user is redirected to once they've signed up

此登录成功通知在您在 application.html.erb 文件中添加的 <p class="notice Átha%= notice %></p> 标签中进行渲染。

在此时,您已在项目中配置了使用 Devise 的用户身份验证,并使用样本帐户登录,您将 Devise 配置为满足应用程序的需求,而 Devise 则生成了促进用户登录体验的路由、视图和控制器。

现在你已经确认注册过程按预期运行,你的下一步是将此身份验证添加到你在 步骤 2中创建的定位页面。

步骤 5 – 将身份验证链接到目标页面

您已在您的项目中设置了所有功能,但您仍然需要将创建的页面链接到您的定位页面。在上一步中,您手动访问了/users/sign_up页面登录,在此步骤中,您将通过添加所需的链接到您的定位页面来链接所有页面。

您将通过一些来自 Devise 的辅助方法来实现这一点。 Devise 宝石配备了许多辅助方法,您可以使用这些方法,而无需自行实现所有内容。

您将开始通过添加代码来检查用户是否已登录. 如果是,目的地页面将显示他们的电子邮件和链接退出应用程序. 如果用户尚未登录,目的地页面将显示链接前往登录页面。

打开app/views/home/index.html.erb文件进行编辑,并添加突出的行:

1[label app/views/home/index.html.erb]
2<% if user_signed_in? %> 
3 <div> Welcome <%= current_user.email %> </div> 
4  <%= button_to "Sign out", destroy_user_session_path, method: :delete %> 
5<% else %>
6  <%= button_to "Sign in", new_user_session_path %> 
7<% end %>
8<h1>Hello DigitalOcean!</h1>

user_signed_in?来自与 Devise 控制器相关联的辅助方法,它检查用户是否已登录并返回 Boolean truefalse 值。 您可以使用此结果在应用程序中编程其他功能,例如显示用户帐户信息,如果他们已登录。 有关该辅助方法的更多细节,您可以在 Devise GitHub 库中检查 源代码

current_user 是一个 Devise 辅助程序,可以访问当前登录到应用程序的用户的详细信息. 例如,如果您使用 [email protected] 登录, current_user 辅助程序将返回 [email protected] 的用户模型。 因此,当您使用 current_user.email 时,您将获得 [email protected] 作为结果。 使用 Devise,您将避免从头开始执行此逻辑,从而节省您的时间和精力。

最后,通过这个代码,您将添加了 ** 登录 ** 和 ** 退出 ** 按钮到目的地页面. 根据user_signed_in? 辅助方法的结果,您将显示使用新添加的 ** 登录 ** 和 ** 退出 ** 按钮的选择。

您正在使用按钮_到方法来定义将用户带到特定路径的按钮,您也在使用辅助方法来获取这些路径:destroy_user_session_path解决为/users/sign_out,new_user_session_path解决为/users/sign_in

保存并关闭文件。

在浏览器中更新您的页面以查看更改。

如果您尚未尝试注册您的应用程序,您可以通过点击您的页面上的 ** Sign in** 按钮访问 /users/sign_in 路径。从这里开始,您可以通过点击底部的 ** Sign up** 链接来创建新帐户。 输入测试电子邮件,如 `[email protected]’ 和密码。 一旦您注册,您将再次被带到目的地页面。 现在,目的地页面显示当前登录用户的电子邮件地址,以及一个 ** Sign out** 按钮,如下所示:

The landing page after the user has signed in

您还会收到一个消息:您已成功注册

有了它,您已经成功集成了 Devise 宝石,并在应用程序中设置了用户身份验证。

结论

在本教程中,您使用 Devise 将用户身份验证添加到 Rails 应用程序中。

要更好地了解 Devise 和其他助手和方法,请查看 Devise GitHub 存储库上的 README 文件。作为本教程的下一步,您可以尝试根据用户是否已登录,在页面上条件地渲染Hello World!问候。

您可以在 DigitalOcean Community GitHub repo中找到该项目的代码。

Published At
Categories with 技术
comments powered by Disqus