Step by Step Ruby on Rails

Ruby on Railsで実際にWebサイトを構築する手順をまとめています。

Ruby on Rails Tutorial AngularJSを使ってユーザーログイン成功時の処理を作成

「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コントローラにログイン成功時のセッション維持の仕組みを追加

$ vi app/controllers/sessions_controller.rb

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