Rails 簡易的實作登入

簡易的實作登入

1. Create a User model

1
2
$ rails g model User name:string password:digest
$ rake db:migrate

2. Modify user.rb to have validations of name(account)

1
2
3
4
class User < ActiveRecord::Base
validates :name, presence: true, uniqueness: true
has_secure_password
end

確保 name 就是帳號是唯一的,然後因為 password 的 type 為 digest 所以預設幫我們使用了 has_secure_password
我們知道當我們在註冊的時候表單常常會要求我們輸入兩次密碼以確保我們設定是正確的,這就是 has_secure_password 幫我們處理的部份
如果我們使用 scaffold 的話,Rails 會自動在幫我們在 model and view 加上這個,這會告訴 Rails 幫我們驗證兩個 passwords 的欄位
接著 view 就會吃 :password, :password_confirmation 兩個參數,如此 model 才會驗證。

在 view 裡面 Rails 會幫我們多一組 password_confirmation 的參數,這個參數實際上並不會建在 db 裡面

3. Gemfile uncomment gem 'bcrypt'

1
$ bundle install

到了這一步我們的 User model 就有驗證的功能。即 User 可以 user.authenticate
接著因為 Rails 會幫我們把 hash 自動從 view 中移除,即不會顯示 password 的資料。所以我們就到 create and update 把導向 :show
的部份移除,直接導回首頁。

調整完 view 之後就可以建立 Session controller。會員 controller 單純管理會員資料,而 SessionController 負責管理登入登出

1
$ rails g controller Sessions new create destroy

在 session 的 create action 中我們必須要記錄一些資料在 session,好讓我們知道該 user 的身份

我們在 session controller 有三個 action 分別為 new, create, destroy

new 用來顯示登入頁面
create 用來登入,建立 session
destroy 用來刪除 session 登出

4. 登入驗證 in Session#create

1
2
3
4
5
6
7
8
9
def create
user = User.find_by(name: params[:name])
if user and user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url
else
redirect_to login_url
end
end

5. 調整 new.html.erb 用來當作登入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="depot_form">
<% if flash[:alert] %>
<p id="notice"><%= flash[:alert] %></p>
<% end %>
<%= form_tag do %>
<fieldset>
<legend>Please Log In</legend>
<div>
<%= label_tag :name, 'Name:' %>
<%= text_field_tag :name, params[:name] %>
</div>
<div>
<%= label_tag :password, 'Password:' %>
<%= password_field_tag :password, params[:password] %>
</div>
<div>
<%= submit_tag "Login" %>
</div>
</fieldset>
<% end %>
</div>

6. 登出片段

1
2
3
4
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out"
end

7. 調整 route

1
2
3
4
5
6
7
Sample::Application.routes.draw do
controller :session do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
end

8. 綁上 before_action in application_controller.rb

1
2
3
4
5
6
7
8
9
10
11
class ApplicationController < ActionController::Base
before_action :authorize

private
def authorize
unless User.find_by(id: session[:user_id])
redirect_to login_url, notice: "Please log in"
end
end

end

9. 不要驗證,在 controller 加上,記住 SessionController 自己本身要加

1
skip_before_action :authorize, only: :create

注意 before_action and before_filter

作者

andyyou(YOU,ZONGYAN)

發表於

2015-04-04

更新於

2021-12-12

許可協議