「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); }; });