在 Rails 實現使用者註冊和登入功能是非常方便的,比如可以使用 Devise 這類實現了完整功能的 gem 擴充包。也可以使用 Rails 內建的 has_secure_password 來自已打造。下面就是嘗試使用 has_secure_password 來實現使用者註冊和登入功能。
準備工作
建立項目:
has_secure_password 中加密的功能需要用到 bcrypt ,所以需要在項目中啟用 bcrypt gem 包。進入項目目錄,修改 Gemfile 檔案如下內容:
# Use ActiveModel has_secure_passwordgem 'bcrypt', '~> 3.1.7'
儲存後退出,執行 bundle install 命令安裝新啟用的 gem 包。
建立使用者模組
操作和系統管理使用者資訊需要先建立儲存使用者的資料表和模型:
rails g model user name:string password_digest:string
password_digest 這個欄位是用來儲存加密混淆後的密碼串的,必須提供並且不能更改成其它名稱,否則無法正常使用 has_secure_password 提供的功能。
然後在使用者模組中引入 has_secure_password 功能:
# app/models/user.rbclass User < ActiveRecord::Base has_secure_passwordend
建立使用者資料表:
實現註冊功能
建立一個 Applicant(申請者) 控制器用來處理使用者註冊:
rails g controller applicants new create
applicants 控制器提供了兩個方法:
- new: 用來處理註冊介面
- create: 用來儲存註冊資訊
上面命令建立的控制器方法,預設使用的都是 get 請求。儲存註冊資訊的 create 方法使用的是 post 請求。所以需要到 config/routes.rb 中修改如下內容:
完成註冊控制器功能:
# app/controllers/applicants_controller.rbclass ApplicantsController < ApplicationController def new @user = User.new end def create @user = User.create(user_params) if @user.save redirect_to :sessions_new else render "new" end end private def user_params params.require(:user).permit(:name, :password, :password_confirmation) endend
完成註冊介面功能:
<!-- app/views/applicants/new.html.erb --><h1>註冊</h1><% if @user.errors.any? %><ul> <% @user.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %></ul><% end %><%= form_for @user, url: :applicants_create do |f| %> <p> <%= f.label :name %> <%= f.text_field :name %> </p> <p> <%= f.label :password %> <%= f.password_field :password %> </p> <p> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation %> </p> <p><%= f.button "提交" %></p><% end %>
這樣就簡單的實現了註冊功能。
實現登入功能
建立一個 Session(會話) 控制器用來處理使用者登入和退出:
rails g controller sessions new create
這裡在 sessions 控制器上預設建立了 2 個方法:
- new: 用來處理登入介面
- create 用來處理登入流程
跟註冊一樣,需要修改 create 的預設路由為 post:
# config/routes.rbpost 'sessions/create'
完成會話控制器的功能:
# app/controllers/sessions_controller.rbclass SessionsController < ApplicationController def new end def create user = User.find_by(name: user_params[:name]).try(:authenticate, user_params[:password]) if user render plain: sprintf("welcome, %s!", user.name) else flash.now[:login_error] = "invalid username or password" render "new" end end private def user_params params.require(:session).permit(:name, :password) endend
完成會話登入介面:
<!-- app/views/sessions/new.html.erb --><h1>登入</h1><% if flash[:login_error] %> <p><%= flash[:login_error] %></p><% end %><%= form_for :session, url: :sessions_create do |f| %> <p> <%= f.label :name %> <%= f.text_field :name %> </p> <p> <%= f.label :password %> <%= f.password_field :password %> </p> <p><%= f.button "登入" %></p><% end %>