「Ruby on Rails Tutorial」のサンプルアプリをAngularJSとBootstrap3を使う形にして作成します。前回ユーザーログイン失敗時の処理を作成したので、今回は、ユーザー処理成功時の処理を追加します。
(1)クッキーによるログイン後のセッション維持の概要
ログイン成功後、セッションを維持するための仕組みクッキーを使って構成します。
①ログイン認証成功後、base64トークンを生成し、ブラウザにパーマネントクッキーとして保存しておく。そしてデータベースに暗号化してbase64トークンを保存する。
②同一セッションの後続のページでは、ブラウザのクッキーからこのトークンを取り出して暗号化し、データベース上で保存されている暗号化トークンと照合させる事によってユーザーを特定する事ができる。
(2)セッション維持機能追加
1)データベースにbase64トークンを保存するカラムを追加
①base64トークンを保存する”remember_token”という名前のカラムをusersテーブルに追加します。
$ rails generate migration add_remember_token_to_users
②”remember_token”を定義し、インデックスを追加
$ vi db/migrate/・・_add_remember_token_to_users.rb
class AddRememberTokenToUsers < ActiveRecord::Migration
def change
add_column :users, :remember_token, :string
add_index :users, :remember_token
end
end
③マイグレーション実行
$ bundle exec rake db:migrate
2)Userモデルにbase64トークンを処理するメソッドを追加
ユーザーを一意に識別するbase64トークン(remember_token)を生成する処理をUserモデルに定義
$ vi app/models/user.rb
class User < ActiveRecord::Base
:
before_create :create_remember_token
:
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
①Userモデルにnew_remember_tokenメソッドを定義
・base64トークンをSecureRandomモジュールにあるurlsafe_base64メソッドを使って生成。
・new_remember_tokenメソッドは、ユーザーのインスタンスに対して動作する必要がないのでインスタンスではなく、Userクラスに属する。(クラスメソッド)
②トークンを暗号化するencryptメソッドをUserモデルに定義
・remember_tokenは暗号化してデータベースに保存するので、そのメソッドを定義します。SHA1を使って暗号化します。
③"before_create"コールバックを定義
・すべてのユーザーが新規作成後すぐにremember_tokenを持つようにするために"before_create"コールバックを使ってremember_tokenを実行します。
・Userオブジェクトのremember_token属性に対して暗号化したトークンを設定するので"self"キーワードをつけます。selfがないとremember_tokenという名前のローカル変数が作成されてしまいます。
・Userモデル内でしか使用しないので"private"キーワードを設定します。
3)sessionsコントローラにログイン成功時のセッション維持の仕組みを追加
def create
user = User.find_by(email: session_params[:email].downcase)
if user && user.authenticate(session_params[:password])
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
@user_info = {
user: user
}
render json: @user_info, status: :accepted, location: user
else
msg = {"password" => ["Invalid email/password combination"]}
render json: msg, status: :unprocessable_entity
end
end
private
def session_params
params.permit(:email,:password)
end
4)AngularJSコントローラにログイン成功時の処理追加
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("SessionsNewCtrl", function($scope, sessionResource, $location) {
$scope.submit = function() {
function success(response) {
$location.path("/users/" + response.user.id);
}
function failure(response) {
:
}
sessionResource.create($scope.session, success, failure);
};
});