0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

railsチュートリアル第九章 ログイン状態を保持

Posted at

###ログイン状態を保持
ユーザーの暗号化済みIDと記憶トークンをブラウザの永続cookiesに保存して、永続セッションを作成する準備ができました。
これを実際に行うにはcookiesメソッドを使います。

####authenticated?をUserモデルに追加する
app/models/user.rb

class User < ApplicationRecord
.
.
.
  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
    # remember_tokenとremamber_digestを比較するもの
    # bycryptで暗号化
    # .is_password?で==の働きをする
    
  end
end

トークンとダイジェストの違いがわからん。
####ログインしてユーザーを保持する
app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
.
.
.
  def create
    user = User.find_by(email: params[:session][:email].downcase)
    # 送信されたメアドを使ってデータベースから取り出す。
    #emailを小文字にする
    if user &.authenticate(params[:session][:password])
    # user  取得したユーザーが有効かどうか?
    # その後にデータベース上にパスワードがあるか?
    # ユーザーログイン後にユーザー情報のページにリダイレクトする
    # &.は省略型
      log_in user
      # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
      remember user
      # ダイジェストをデータベースに記憶させる
      redirect_to user
      # 名前付きルート/userのビューを表示する
    else
      flash.now[:danger] = 'Invalid email/password combination'
      # flash.nowでリクエストが発生後メッセージを消滅する
      # エラーメッセージを作成する
        render 'new'
        # newアクションのビューを表示
    end
  end
.
.
.
end

####ユーザーを記憶する
app/helpers/sessions_helper.rb

module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
    #sessionメソッドで作成した一時cookiesは自動的に暗号化される
    # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
  end
  
   # ユーザーのセッションを永続的にする
  def remember(user)
    user.remember
    # userをデータベースに保存
    cookies.permanent.signed[:user_id] = user.id
    # signed.permanent ユーザーidと記憶トークンを結びつける
    # 攻撃者に奪い取られる可能性があるため
    cookies.permanent[:remember_token] = user.remember_token
  end
.
.
.
end

####永続的セッションのcurrent_userを更新する
app/helpers/sessions_helper.rb

class User < ApplicationRecord
.
.
.
  # 記憶トークンcookieに対応するユーザーを返す
  def current_user
    if (user_id = session[:user_id])
    # ログイン中のidを代入する
    # 永続セッション(ログイン中)にするため
      @current_user ||= User.find_by(id: user_id)
      # カレントユーザーまたは検索結果があったものを代入する
    elsif (user_id = cookies.signed[:user_id])
    # そうでなければ 書名付きクッキーを代入
      user = User.find_by(id: user_id)
      # idでユーザーを探す
      if user && user.authenticated?(cookies[:remember_token])
     # ユーザーが有効であり、記憶トークンも認証されたら
        log_in user
        # ログインする
        @current_user = user
        # カレントユーザーに代入するかな
        
      end
    end
  end
.
.
.
end

テスト

ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 8950
Started with run options --seed 17566

ERROR["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x000055a0ef5c93c0 @name="UsersLoginTest">, 1.6133994830006486]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (1.61s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method ` ' for #<#<Class:0x000055a0eef11190>:0x000055a0ef288cb0>
            app/helpers/sessions_helper.rb:32:in `current_user'
            app/helpers/sessions_helper.rb:43:in `logged_in?'
            app/views/layouts/_header.html.erb:8
            app/views/layouts/application.html.erb:9
            test/integration/users_login_test.rb:43:in `block in <class:UsersLoginTest>'

  24/24: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.99939s
24 tests, 58 assertions, 0 failures, 1 errors, 0 skips

ActionView::Template::Error: undefined local variable or method

###演習
1.
ブラウザのcookieを調べ、ログイン後のブラウザではremember_tokenと暗号化されたuser_idがあることを確認してみましょう。

確認
2.
コンソールを開き、リスト 9.6のauthenticated?メソッドがうまく動くかどうか確かめてみましょう。

>> user = User.first
   (1.6ms)  SELECT sqlite_version(*)
  User Load (0.8ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "a", email: "abc@def.com", created_at: "2021-10-05 04:11:41", updated_at: "2021-10-09 07:53:18", password_digest: [FILTERED], remember_digest: "$..">

>> user.authenticated?
Traceback (most recent call last):
        2: from (irb):2
        1: from app/models/user.rb:48:in `authenticated?'
ArgumentError (wrong number of arguments (given 0, expected 1))
#引数を一つ欲しいらしい。

>> user.authenticated?("")
=> false
>> user.authenticated?("aaaaaa")
=> false
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?