作者選擇了Girls Who Code作為Write for DOnations計劃的捐贈對象。
簡介
Devise 寶石是一個針對Ruby on Rails應用的身份驗證解決方案;它幫助您在項目中設置生產就緒的用戶身份驗證,而無需自己動手做所有事情。Devise提供許多有用的功能,例如處理用戶會話,並使用OmniAuth 寶石添加對第三方OAuth登錄的支持。Devise還配備了內置模塊,用於重置忘記的密碼,跟踪登錄次數和時間戳,定義超時,鎖定帳戶等功能。
Devise使用戶身份驗證變得非常簡單,只需初始化該寶石並創建一個具有所需功能的User
模型。如果您要從頭開始構建用戶身份驗證系統,則需要為所需功能編寫代碼和測試,並處理會話管理、存儲Cookie和保護數據安全等所有邊緣情況。通過使用Devise寶石,您可以避免自己做所有這些工作,而可以專注於構建應用程序。
在這個教程中,您將使用Rails創建一個最小的 Web 應用程序,並安裝 Devise,這將允許用戶創建帳戶、登錄和從他們的帳戶登出。
先決條件
完成本教程,您將需要:
- A local development environment for Ruby on Rails. For Linux, you can follow our tutorial How To Install Ruby on Rails with
rvm
on Ubuntu 20.04 or use thervm
product docs for installing on Mac or Windows. You can also refer to the Ruby project docs to install Ruby directly in your system. To install the Rails gem, you can use the official Rails documentation. The Devise gem requires Ruby version 2.1.0 or greater; this tutorial was tested using Ruby version 3.0.2 and Rails version 7.0.3. - 在您的機器上安裝了 Node.js。一些 Rails 功能,如 Asset Pipeline,依賴於 JavaScript Runtime。Node.js 提供此功能。對於 Ubuntu,請使用官方 PPA 安裝 Node.js,如在如何在 Ubuntu 20.04 上安裝 Node.js的選項 2 中所述。對於 MacOS,請遵循我們的指南如何在 MacOS 上安裝 Node.js 並創建本地開發環境。
- 熟悉 Ruby 和 Ruby on Rails 框架。您可以查看我們系列教程容器上的 Rails的前幾篇,或者您可以使用官方Rails 指南。
步驟 1 — 建立新的 Rails 應用程式
在此步驟中,您將建立一個新的 Rails 應用程式並在本機上運行它。您將使用 rails
命令列工具初始化專案。
從終端機執行以下命令:
- rails new blog
rails new
命令將在目錄 blog
下創建一個新的 Rails 專案,其中包含許多生成的文件和文件夾。其中之一是 Gemfile,其中包含專案的相依性。您將在 步驟 3 — 安裝並配置 Devise 中配置 Gemfile 以使用 Devise。
注意:如果您收到一條錯誤訊息說明 找不到 gem
,您可以通過切換到專案目錄(cd blog
)並運行 bundle install
來解決它,這將安裝在您的 Gemfile
中列出的所有 gem。
您可以使用喜歡的文本編輯器打開此目錄,或者使用終端機進入:
- cd blog
要啟動 Rails 應用程式,請使用 rails server
命令從專案目錄啟動開發伺服器:
- bundle exec rails server
這個指令將啟動 Rails 開發伺服器。在瀏覽器中打開 http://localhost:3000
以訪問 Rails 歡迎頁面。如果未提供替代的埠號,Rails 將使用埠號 3000
運行應用程序。
**注意:**將 bundle exec
附加到您的指令中,可在當前 bundle 的上下文中執行它。這意味著只會使用特定於項目的 Gemfile 及其中定義的 gem 版本。如果全局安裝了相同 gem 的不同版本,這將很有用。
您現在已初始化一個新的 Rails 應用程序,稍後將在其中添加使用者驗證。在下一步中,您將使用自定義登陸頁面替換 Rails 提供的默認首頁,這將使在添加 Devise 後更容易導航通過示例應用程序。創建新的登陸頁面後,您將添加用於用戶註冊和登錄應用程序的鏈接。
第 2 步 – 創建登陸頁面
現在您有了基本的 Rails 應用程序,將使用自己的登陸頁面替換 Rails 提供的默認頁面。自定義登陸頁面將更容易為用戶顯示在應用程序的根 URL 上註冊和登錄的鏈接。您將在以後的步驟中添加 登錄
和 註冊
的鏈接。
要創建您的登陸頁面,您需要執行以下操作:
- 在
config/routes.rb
文件中添加路由。 - 创建一个
HomeController
,它将处理对该路由的请求。 - 创建一个视图文件,该文件将在访问该路由时呈现。
首先,在创建项目时生成的routes.rb
文件中添加根路径。
使用nano
或您喜欢的文本编辑器,打开之前生成的config/routes.rb
文件:
- nano config/routes.rb
添加突出显示的行:
Rails.application.routes.draw do
root to: "home#index"
end
root to:
定义将处理根路径请求的控制器动作,即在这种情况下,该路由将是http://localhost:3000
,这是Rails应用程序的默认端口。对这个路由的请求将由home
控制器中的index
动作处理。此文件现在不存在,因此您将创建app/controllers/home_controller.rb
文件。
保存并关闭config/routes.rb
。使用nano
,按CTRL+X
退出,Y
保存,然后按ENTER
确认文件名并关闭文件。
接下来,创建app/controllers/home_controller.rb
文件并添加以下行:
class HomeController < ApplicationController
def index
render
end
end
这是一个基本的HomeController
,带有一个执行一项操作的index
方法:呈现与控制器动作关联的视图文件。
在這種情況下,視圖檔案將是app/views/home/index.html.erb
檔案。 您需要創建此文件以及app/views
目錄內的home
目錄。
保存並關閉home
控制器文件。
接下來,在app/views
目錄中創建home
目錄:
- mkdir app/views/home/
home
目錄將保存特定Rails控制器的所有視圖。
然後,創建app/views/home/index.html.erb
文件並添加以下行:
<h1>Hello DigitalOcean!</h1>
app/views/home/index.html.erb
是視圖文件,Home
控制器的index
動作將要渲染的文件。 這是一個HTML文件,您可以在其中嵌入Ruby代碼。 當針對特定控制器動作定義的路由啟動時,將在用戶的瀏覽器中呈現此視圖文件。
保存並關閉您的文件。
要查看根URL中的更改,請在您的瀏覽器中打開http://localhost:3000
(或者如果已經打開,請刷新頁面)。 更新後的首頁將類似於此:
如果需要,您可以進一步自定義此頁面,但對於本教程,這就是所需的全部。
現在您已經有了一個簡單的Rails應用程序及其自己的首頁,您將使用Devise gem添加用戶身份驗證。
第3步 — 安裝和配置 Devise
在這一步中,您將在您的 Rails 應用程序中安裝和配置 Devise,以便您可以使用該 gem 提供的方法和幫助程序。您將使用 user_signed_in?
方法來檢查存儲在瀏覽器 cookies 中的任何已登錄用戶的會話信息。您還將使用 current_user
幫助程序來獲取當前已登錄的帳戶的詳細信息。這兩種方法都內置於 Devise 中,您可以直接在應用程序中使用它們,而無需編寫額外的代碼。您可以從 Devise 項目的 GitHub 頁面 了解更多有關這些幫助方法的信息。
安裝 Devise 的第一步是將 gem 添加到您的 Gemfile 中,該文件包含有關運行 Ruby 項目所需的所有依賴項的信息。在這種情況下,當您初始化 Rails 應用程序時,生成的 Gemfile 已經包含了運行 Rails 所需的所有基本 gem。
但在對 Gemfile 進行更改之前,請停止您在上一步中啟動的開發服務器,方法是在運行該服務器的終端中按下 CTRL+C
。
然後,打開要編輯的 Gemfile。要添加 Devise gem,請將突出顯示的行添加到文件的末尾,但在 development
和 test
組之外:
# ...
# 通過緩存減少啟動時間;在 config/boot.rb 中需要
gem "bootsnap", require: false
# 使用 Active Storage 變體 [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
gem "devise"
group :development, :test do
# 請參閱 https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
end
# ...
保存並關閉您的文件。
接下來,您將通過在終端中運行bundle install
命令來安裝新添加的 gem。從您的項目目錄(blog
)運行以下命令:
- bundle install
此命令將在您的項目中安裝 Devise gem,這將使您能夠使用rails
命令行工具中的devise
命令並配置身份驗證。
要在項目中設置 Devise,請運行生成器命令:
- bundle exec rails g devise:install
上述命令中的g
標誌代表generate
,用於調用 Rails 生成器。生成器將創建可作為起點的文件。您可以閱讀Rails 指南以獲取有關 Rails 生成器的更多信息。
先前的命令會生成多個文件,包括初始化文件和 Devise 的 i18n 地區文件。初始化文件如下詳細說明,用於在應用程序首次啟動時配置 Devise。i18n代表國際化,這是一個標準,可幫助您在不同語言運行應用程序。
此時,終端上也會打印一些指示,如下:
Output===============================================================================
Depending on your application's configuration some manual setup may be required:
1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
In production, :host should be set to the actual host of your application.
* Required for all applications. *
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
* Not required for API-only Applications *
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
* Not required for API-only Applications *
4. You can copy Devise views (for customization) to your app by running:
rails g devise:views
* Not required *
===============================================================================
雖然本教程不需要進行手動設置,但稍後您將在此步驟中為提示
和警告
添加快閃消息。
您已完成安裝 Devise。接下來,您需要在剛生成的 Devise 初始化文件中配置一些東西。
當您運行devise:install
命令時,將生成config/initializers/devise.rb
,這是 Devise 的初始化文件。每當啟動 Rails 應用程序時,Rails 將加載所有 gem 和插件,然後將加載所有初始化文件。您可以從這些初始化文件中為應用程序的不同部分配置特定設置。所有這些初始化程序都位於config/initializers/
目錄中,這也是 Devise gem 創建其初始化程序的位置。
打開config/initializers/devise.rb
進行編輯。在文件中,找到Devise.setup
塊,並添加以下突出顯示的行(Devise.setup
塊中可能還有其他代碼塊,但您可以忽略它們):
Devise.setup do |config|
# ...
config.navigational_formats = ['*/*', :html, :turbo_stream]
# ...
end
這行將turbo_stream
添加為導航格式。 Turbo Streams是Turbo的一部分,它允許您發送服務器呈現的HTML並在不使用太多JavaScript的情況下呈現頁面。您需要添加這個,以使Devise 4.8.1
能夠與Rails 7一起使用;否則,您將收到undefined method user_url
錯誤。
保存並關閉文件。
接下來,您還將添加在先前打印的說明中突顯的通知和警告閃爍消息。 alert
和notice
標籤是顯示界面中出現的“密碼不正確”等消息的地方。您始終可以在應用程序中實現自定義警報消息(例如,如果您使用React作為前端的Axios攔截器),但在本教程中,您將完成Devise的最低限度設置。
打開app/views/layouts/application.html.erb
進行編輯。在body標記的正上方<%= yield %>
,添加"notice"
和"alert"
消息的標籤:
...
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
當視圖在瀏覽器中呈現時,<%= yield %>
區塊將被來自視圖文件的內容替換。在您的視圖文件中,您只有p
標籤。此yield標記將被該內容替換。
保存並關閉您的文件。
在此步驟中,您已在您的專案中安裝並配置了 Devise。在下一步,您將使用 Devise 創建應用程式的使用者模型並設置使用者身份驗證。
第4步 — 使用 Devise 創建使用者模型
您現在可以使用 Devise 生成使用者模型,這將創建必要的模型文件並生成一個遷移,您可以運行它來在應用程式中創建一個 users
表。每當有人註冊時,您需要在數據庫中的 users
表中創建一條新記錄。有了使用者模型,您可以從前端檢視操作這些數據庫記錄。
在此步驟中,您將生成一個使用者模型,檢查默認配置,然後運行遷移以更新您的數據庫。
由於 Rails 是一個 模型-視圖-控制器(MVC)框架,每個數據庫表都有與之相關聯的類,可用於處理表中的數據。在這種情況下,如果您創建一個 users
表,您可以使用 User
模型執行像 User.first
或 User.find_by_email("[email protected]")
之類的操作。您可以通過在 Rails 中創建一個繼承自 ApplicationRecord
的正常類來創建此模型,但使用 Devise 生成使用者模型可以為您提供可以用於身份驗證的多個方法。
要創建您的Devise用戶,運行以下生成器命令:
- bundle exec rails g devise user
以下輸出將打印到屏幕上:
Outputinvoke active_record
create db/migrate/20220908152949_devise_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
insert app/models/user.rb
route devise_for :users
輸出顯示Devise生成了幾個文件,創建了測試並添加了路由。第一個文件db/migrate/20220908152949_devise_create_users.rb
是用於在數據庫中創建users
表的遷移文件。Rails遷移文件描述了需要在數據庫中進行的更改。每個遷移的文件名將包含一個時間戳,以便Rails知道以何種順序進行這些更改。
Devise還創建了用戶模型文件(app/models/user.rb
),以及相應的測試。輸出的最後一行表明將路由添加到現有的config/routes.rb
文件中。Devise自動添加所有路由,如/users/sign_up
和/users/sign_out
,使用devise_for :users
輔助。
在運行遷移文件並在數據庫中創建users
表之前,讓我們查看這些生成的文件。這將幫助您了解Devise生成的配置,以便在運行遷移時知道發生了什麼。
首先打開遷移文件(db/migrate/20220908152949_devise_create_users.rb
)來查看默認代碼:
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
Devise 包含許多有用的選項,像是用於密碼重設令牌和最後一個令牌發送時間的字段,等等。還有像是電子郵件確認、在登入失敗嘗試後鎖定使用者、甚至追踪登入詳細資訊的功能。
因為你不需要進行任何更改,所以關閉遷移檔案。
Devise 也生成了 User
模型文件。该文件可在 app/models/
目录中找到。
打开 app/models/user.rb
模型文件,查看默认代码:
class User < ApplicationRecord
# 包括默认的 Devise 模块。其他可用的有:
# :confirmable, :lockable, :timeoutable, :trackable 和 :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
A few options are added by Devise to configure how the user model works. The basic modules (database_authenticatable
, registerable
, recoverable
, rememberable
, and validatable
) are already included. There are some additional options commented out, corresponding to the extra features you saw in the migration file. You can add these modules to the model file and configure the migration, depending on how much functionality you need in your application.
以下是基本模块的作用:
database_authenticatable
: 用户可以使用登录和密码字段进行身份验证。他们的加密密码将存储在数据库中。registerable
: 用户可以注册并编辑或删除他们的帐户。recoverable
: 用户可以重置密码并恢复他们的帐户,如果他们忘记了凭据。rememberable
: 此模块通过将信息保存在浏览器 cookie 中来记住用户的会话。validatable
: 此模块为用户的电子邮件和密码字段提供验证。(例如,即使您在模型中未定义任何自定义验证,您的应用程序也要求密码至少为六个字符。)
这些基本模块已包含在刚刚生成的 User 模型中。您可以在 Devise GitHub 存储库 中找到附带 Devise 的完整模块列表。
您不需要进行任何更改,因此关闭 User
模型文件。
另一個更新是 config/routes.rb
文件已被修改,以添加一個 devise_for
行用於 users
:
Rails.application.routes.draw do
devise_for :users
root "home#index"
end
這是一個有用的方法,它定義了所有與用戶身份驗證相關的必需路由,如 /users/sign_in
、/users/sign_out
和 /users/password/new
。 Devise 會為您處理所有這些,甚至還能保持路由文件的整潔。 如果您想了解如何將 devise_for :users
添加到所有這些路由的自動轉換,您可以查看 Devise GitHub 存儲庫 中該方法的源代碼。
您不需要在這裡進行任何更改,因此請關閉 config/routes.rb
文件。
要了解應用程序定義了哪些路由,您可以運行以下命令列出它們:
- bundle exec rails routes
此命令打印所有應用程序路由以及這些路由正在處理的控制器。 在身份驗證的情況下,所有這些路由都是由 Devise 創建的,您不必手動添加它們。
輸出將會很長,但以下是一小段顯示的一些路由:
Prefix | Verb | URI Pattern | Controller#Action |
---|---|---|---|
new_user_session | GET | /users/sign_in(.:format) | devise/sessions#new |
user_session | POST | /users/sign_in(.:format) | devise/sessions#create |
destroy_user_session | DELETE | /users/sign_out(.:format) | devise/sessions#destroy |
new_user_password | GET | /users/password/new(.:format) | devise/passwords#new |
edit_user_password | GET | /users/password/edit(.:format) | devise/passwords#edit |
user_password | PATCH | /users/password(.:format) | devise/passwords#update |
PUT | /users/password(.:format) | devise/passwords#update | |
POST | /users/password(.:format) | devise/passwords#create | |
cancel_user_registration | GET | /users/cancel(.:format) | devise/registrations#cancel |
在輸出中列出的路由是在您的路由文件中包含 devise_for :users
行時 Devise 添加的路由。 這些是用於操作,如 sign in
、sign up
、reset password
等的路由。
現在您已經檢閱了由Devise生成的文件和配置,您可以使用以下命令運行在此步驟開始時生成的遷移:
- bundle exec rails db:migrate
上述命令將對數據庫中的每個遷移文件進行所有更改。這些更改需要按照文件中定義的順序逐個進行。Rails需要知道遷移應該運行的順序,這就是為什麼文件的名稱中帶有時間戳記的原因。
類似以下的輸出將顯示在屏幕上:
Output== 20220908152949 DeviseCreateUsers: migrating ================================
-- create_table(:users)
-> 0.0040s
-- add_index(:users, :email, {:unique=>true})
-> 0.0012s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0011s
== 20220908152949 DeviseCreateUsers: migrated (0.0074s) =======================
遷移運行後,您的數據庫已設置完成。您已完成了在項目中設置用戶身份驗證所需的一切。
此時,請重新啟動您的Rails服務器:
- bundle exec rails server
之前提到的初始化文件僅在Rails啟動時加載。您需要重新啟動服務器,以便Rails可以加載新的Devise初始化文件並為用戶身份驗證設置一切。
在瀏覽器中轉到http://localhost:3000/users/sign_up
,您將找到一個註冊表單,通過輸入電子郵件和密碼來創建帳戶。(在下一步中,您將在登陸頁面上添加用於註冊和登錄的按鈕,以使讀者更輕鬆地導航到此URL。)
要測試身份驗證,請輸入一個測試電子郵件,例如[email protected]
和一個密碼。
一旦您註冊,您將被重定向到根頁面,該頁面顯示Hello DigitalOcean!以及一條消息,表示您已成功註冊,如下所示:
此註冊成功通知以<p class="notice"><%= notice %></p>
標籤呈現,該標籤是您在application.html.erb
文件中添加的。
此時,您已在項目中使用Devise配置了用戶驗證並使用示例帳戶註冊。您根據應用程序的需求配置了Devise,而Devise生成了路由、視圖和控制器,以實現此用戶註冊體驗。
既然您確認註冊過程符合預期,下一步是將此身份驗證添加到您在第2步創建的登錄頁面上。在下一步中,您將鏈接註冊頁面與登錄頁面,這樣用戶就不必像您在這裡所做的那樣導航到特定的URL才能註冊。
第5步-將身份驗證鏈接到登錄頁面
你的專案中已經設定好所有功能,但你仍然需要將 Devise 建立的頁面與你的登錄頁面連接起來。在前一步驟中,你手動訪問了 /users/sign_up
頁面進行登錄。在這一步中,你將通過在登錄頁面添加所需的連結來將所有頁面連接在一起。你還將有條件地根據用戶的狀態顯示用戶登錄或登出應用程序的連結。
你將使用 Devise 中的一些輔助方法來完成這個任務。Devise gem 提供了許多輔助方法,你可以在不必自己實現一切的情況下使用它們。這使得代碼更容易閱讀和維護。
你將首先添加代碼來檢查用戶是否已經登錄。如果是,登錄頁面將顯示他們的電子郵件以及登出應用程序的鏈接。如果用戶未登錄,登錄頁面將顯示一個鏈接,指向登錄頁面。
打開 app/views/home/index.html.erb
文件進行編輯,添加以下突出顯示的代碼行:
<% if user_signed_in? %>
<div> Welcome <%= current_user.email %> </div>
<%= button_to "Sign out", destroy_user_session_path, method: :delete %>
<% else %>
<%= button_to "Sign in", new_user_session_path %>
<% end %>
<h1>Hello DigitalOcean!</h1>
user_signed_in?
來自於 Devise 控制器相關的輔助方法。它檢查用戶是否已登錄,並返回布爾值 true
或 false
。你可以使用這個結果來在應用程序中編程其他功能,例如在用戶已登錄時顯示用戶的帳戶信息。有關此輔助方法的更多詳細信息,你可以查看 Devise GitHub 存儲庫中的 源代碼。
`current_user` 是一個 Devise 輔助工具,用於訪問當前已登錄應用程序的用戶的詳細信息。例如,如果您使用 `[email protected]` 登錄,`current_user` 輔助工具將返回 `[email protected]` 的用戶模型。因此,當使用 `current_user.email` 時,您將得到 `[email protected]` 作為結果。通過使用 Devise,您避免了從頭開始實現此邏輯,從而節省了時間和精力。
最後,使用此代碼,您在登錄頁面上添加了 登錄 和 登出 按鈕。根據 `user_signed_in?` 輔助方法的結果,您將顯示使用新添加的 登錄 和 登出 按鈕的選項。
您正在使用 `button_to` 方法定義一個按鈕,該按鈕將用戶帶到特定的路由。您還在使用輔助方法獲取這些路由:`destroy_user_session_path` 解析為 `/users/sign_out`,`new_user_session_path` 解析為 `/users/sign_in`。(您可以通過運行先前步驟中提到的 `bundle exec rails routes` 來查看路由 URL 輔助工具的完整列表。)
保存並關閉文件。
在瀏覽器中刷新頁面以查看更改。
如果您尚未尝试注册您的应用程序,您可以通过单击页面上的登录按钮访问/users/sign_in
路由。从这里,您可以通过单击底部的注册链接继续创建新帐户。输入一个测试电子邮件,如[email protected]
,和一个密码。注册后,您将再次返回到登陆页面。现在,登陆页面显示当前已登录用户的电子邮件地址,以及一个退出按钮,如下所示:
您还会收到一条消息,内容为:您已成功注册
。
通过这样,您已成功集成了Devise宝石并在应用程序中设置了用户身份验证。
结论
在本教程中,您使用了Devise为Rails应用程序添加用户身份验证。使用Devise的辅助方法,您创建了一个允许用户创建帐户、注册和退出的应用程序。
要更好地了解Devise以及其他辅助方法,请查看Devise GitHub存储库上的README文件。作为本教程的下一步,您可以尝试根据用户是否已登录有条件地在页面上呈现“Hello World!”问候语,例如Hello username
。
你可以在DigitalOcean 社群 GitHub 存儲庫中找到此專案的代碼。