ユーザ登録にメール認証によるアカウント有効化機能を付加したときの流れ
目的
Webアプリケーションへのユーザ登録の際、入力されたEメールが本当に存在するかを確認した上でユーザ登録する機能を実装しました。
そのときのユーザ側の動きとサーバ側の動きをまとめました。
コードは認証失敗などの処理が無い前提で使う部分だけ記載しています。
※Railsチュートリアル11章の内容です。
処理の流れ
1.ユーザ側で登録する情報を入力してもらう。その際、Eメールは必須項目。
2.ユーザが送信ボタンを押したとき、新しいユーザレコードが作成されサーバ側でtokentとdigestを作成
・Tokenはユーザ端末に保存またはユーザが入力する鍵となる値
・digestはtokenを元に生成される不可逆的なハッシュ値。サーバ側に保存される。
#新しいユーザが作成される(User.createが実行される)際は
#before_createによりcreate_activation_digestが実行
#Userモデル
class User < ApplicationRecord
before_create :create_activation_digest
def create_activation_digest
#Tokenの生成
self.activation_token = User.new_token
#digestの生成
self.activation_digest = User.digest(activation_token)
end
# 渡された文字列のハッシュ値を返す
# BCryptのGEMを使用(gem 'bcrypt')
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
#ランダムなトークンを返す
def User.new_token
SecureRandom.urlsafe_base64
end
end
#Usersコントローラ
class UsersController < ApplicationController
def create
@user = User.new(user_params)
#ここで上記のUser.create_activation_digestが実行
if @user.save
@user.send_activation_email
#省略
else
#省略
end
end
end
#またUserモデル
class User < ApplicationRecord
def send_activation_email
UserMailer.account_activation(self).deliver_now
#selfはUsersControllerの@user
end
end
#Userメーラー
class UserMailer < ApplicationMailer
def account_activation(user)
@user = user
mail to: user.email, subject: "Account activation"
end
end
上記によりユーザへメールが送付される。
3.ユーザが入力したEメールアドレスに、サーバがアカウント認証用のEメールを送付する。
・Eメールの本文には、EメールアドレスとTokenを含めたURLへのリンクが記載されている。
"Activate"のリンクには下記のURLへリンクが貼られている。
https://fqdn/account_activations/<Token>/edit?email=<Email>
例:https://fqdn/account_activations/T5oNDqEPDZKQGzrIje3OjA/edit?email=test%40email.com
ユーザは、このEメールアドレスとTokenが含まれたURLをクリックしてアクセスする。つまり、ブラウザのアドレスバーにEメールとTokenを入力してサーバに送信することとなる
4.サーバ側で入力されたTokenからdigestを生成、そして入力されたEメールをキーにしてユーザを参照する。
URLに含まれるPathは"account_activations/:id/edit"の形となるので
AccountActivationsコントローラのeditアクションが実行される。
5.参照したユーザのレコードに保存されているdigestとユーザが入力したTokenから生成したdigestが一致することを確認。
#AccountActivationsコントローラ
class AccountActivationsController < ApplicationController
def edit
user = User.find_by(email: params[:email])
#URLに含まれるEメールアドレスをキーにしてユーザ情報を取得
if user && !user.activated? && user.authenticated?(:activation, params[:id])
#ユーザが存在する、かつ、ユーザのactivatedカラムがtrueではない、かつ、ユーザ認証が成功したときを条件として、ユーザを有効化
#.activated?はカラム"activated"を指す。.authenticated?はUserモデルのメソッドを指す
#":activation"は下に記載するUserモデルのメソッドで
# activation_digestのメソッドの文字列を作るメタプログラミングのための引数
user.activate
log_in user
#省略
else
#省略
end
end
end
#またまたUserモデル
class User < ApplicationRecord
# 渡されたトークンがダイジェストと一致したらtrueを返す
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
#アカウントを有効にする
def activate
update_columns(activated: true, activated_at: Time.zone.now)
end
end
#Sessionsヘルパーモジュール
module SessionsHelper
#渡されたユーザでログインする
def log_in(user)
session[:user_id] = user.id #:user_idはハッシュキー
end
end
#補足:Sessionsヘルパーモジュールを他のコントローラでも使えるようにApplicationコントローラで定義
class ApplicationController < ActionController::Base
include SessionsHelper #セッションコントローラ以外でも使えるようにする
end
コントローラとかモデルとかメーラーとかヘルパーとか行ったり来たりでこの流れを理解して覚えるのはちょっと時間かかるかなー。。。
Author And Source
この問題について(ユーザ登録にメール認証によるアカウント有効化機能を付加したときの流れ), 我々は、より多くの情報をここで見つけました https://qiita.com/kitsunecat/items/5c8e0c079e067fd2ec0b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .