[Rails] 비밀번호 변경(토큰은 어떻게 사용하나요)

17030 단어 RubyRails

개시하다


sorcery의 암호 리셋 기능이 실현되었습니다.
아래 세 가지를 기술했으니 관심 있으면 보세요.
1. sorcery 비밀번호 리셋 기능을 실현하는 방법
2. ActionMailer의 사용 방법
3. password 리셋 영패는 요청/응답 사이에서 어떻게 사용하는가

1.sorcery의resetpassword 설치


모듈 구현 및 마이그레이션 파일 생성


  • 실행rails g sorcery:install reset_password --only-submodulespassword reset용 모듈의 설치, 마이그레이션 파일을 만듭니다.
  • $ rails g sorcery:install reset_password --only-submodules
    Running via Spring preloader in process 99290
            gsub  config/initializers/sorcery.rb
          insert  app/models/user.rb
          create  db/migrate/20200419075054_sorcery_reset_password.rb
    
  • sorcery의 정의 파일config/initializers/sorcery.rb에서passwordreset 서브 모듈을 사용하는 데 사용할 설명을 자동으로 실행합니다.
  • config/initializers/sorcery.rb
    Rails.application.config.sorcery.submodules = [:reset_password]
    

    User 모델 allow트루 추가

  • password_reset_토큰에 독특한 제약과allow_nil: true를 부여한다.
  • 비밀번호 변경 시 resetpassword_토큰은 닐이기 때문에 독특한 제약에 끌린다.그리하여리얼리티를 더해서 미리 니엘을 허락합니다.
  • user.rb
    validates :reset_password_token, uniqueness: true, allow_nil: true
    

    2. 비밀번호 재설정을 위한 Mailer 만들기


    application_mailer.rb 설정


    메일 원본과 Mailer 보기를 보내는 일반적인 레이아웃의 파일을 지정합니다.
  • 우편물의 발송인을 [email protected]로 설정합니다.
  • 레이아웃 파일은 app/views/layouts/mailer.html.erbapp/views/layouts/mailer.text.erb입니다.
  • app/mailers/application_mailer.rb
    class ApplicationMailer < ActionMailer::Base
      # メールの差し出し元
      default from: '[email protected]'
      layout 'mailer'
    end
    

    암호 재설정을 위한 제조업체 설정

  • 실행rails g mailer UserMailer change_password_email, 비밀번호 재설정을 위한 제조업체 UserMailer를 만듭니다.
  • config/initializers/sorcery.rb에서 UserMailer는 sorcery 암호를 재설정하는 Action Mailer로 지정됩니다.
  • user.reset_password_mailer = UserMailer의 UserMailer로 추정app/mailers/user_mailer.rb.
  • config/initializers/sorcery.rb
    Rails.application.config.sorcery.submodules = [:reset_password, blabla, blablu, ...]
    
    Rails.application.config.sorcery.configure do |config|
      config.user_config do |user|
        user.reset_password_mailer = UserMailer # パスワードリセット用のMailerにUserMailerが指定されている
      end
    end
    

    암호 재설정 방법 설명

  • 메일(user mailer.rb)을 편집하고 비밀번호 리셋용 메일을 보내는 방법을 만들어 파라미터에 user 파라미터를 추가합니다.
  • 메일(view)에 표시할 정보와 메일의 발송 목적지를 설정합니다.

  • Mailer 클래스 # 메서드는 컨트롤러 # 메서드와 비슷한 동작을 수행합니다.
    UserMailerchange_password_email방법으로user_mailer/change_password_email.html.erb의 주시도를 추측하여 호출한다.
  • app/mailers/user_mailer.rb
    class UserMailer < ApplicationMailer
    
      # change_password_emailメソッドなので、change_password_email.〇〇のビューがメールのフォーマットになる
      # コントローラの場合と同様、メイラーのメソッド内で定義されたインスタンス変数はメイラーのビューで使える。
      def change_password_email(user)
        @user = User.find(user.id)
        @url  = edit_password_change_url(@user.reset_password_token)
        mail(to: user.email,
             subject: 'パスワードリセット')
      end
    end
    

    홈 뷰 설정


    이것은 실제 우편물의 본문이다.
    app/views/user_mailer/change_password_email.html.erb
    <%= @user.name %><p>以下のリンクからパスワードの再発行を行ってください。</p>
    
    <p><a href="<%= @url %>"><%= @url %></a></p>
    
    app/views/user_mailer/change_password_email.text.erb
    <%= @user.name %>様
    ===========================================
    
    以下のリンクからパスワードの再発行を行ってください。
    <%= @url %>
    

    3. 컨트롤러 설정


    암호 재설정을 위한 컨트롤러 # 동작이 rails g controller PasswordChanges new create edit update에 추가되었습니다.
    app/controllers/password_changes_controller.rb
    class PasswordChangesController < ApplicationController
      skip_before_action :require_login
    
      # パスワードリセット申請フォーム用のアクション
      def new; end
    
      # パスワードリセットをリクエストするアクション
      # ユーザーがパスワードのリセットフォームにemailを入力し、送信したときにこのアクションが実行される
      def create
        # form_withで送られてきたemailをparamsで受け取る
        @user = User.find_by(email: params[:email])
        # DBからデータを受け取れていれば、パスワードリセットの方法を記載したメールをユーザーに送信する(ランダムトークン付きのURL/有効期限付き)
        @user&.deliver_reset_password_instructions! 
        # 上記は、@user.deliver_reset_password_instructions! if @user と同じ
    
        # フォームに入力したemailがアプリ(DB)内に存在するか否かを問わず、リダイレクトして成功メッセージを表示させる。
        # DBに存在した時だけ成功メッセージを表示させると、DB内にそのemailが存在するかどうかを悪意ある第三者でさえも確認できてしまう。
        redirect_to login_path, success: "成功しました"
      end
    
      # パスワードリセットフォームページへ遷移するアクション
      def edit
        # postされてきた値を取得
        @token = params[:id]
        # リクエストで送信されてきたトークンを使って、ユーザーの検索を行い, 有効期限のチェックも行う。
        # トークンが見つかり、有効であればそのユーザーオブジェクトを@userに格納する
        @user = User.load_from_reset_password_token(params[:id])
        # @userがnilまたは空の場合、not_authenticatedメソッドを実行する
        return not_authenticated if @user.blank?
      end
    
      # ユーザーがパスワードのリセットフォームを送信(新しいパスワードの入力)したときに実行される
      def update
        @token = params[:id]
        @user = User.load_from_reset_password_token(@token)
        return not_authenticated if @user.blank?
        # password_confirmation属性の有効性を確認
        @user.password_confirmation = params[:user][:password_confirmation]
        # change_passwordメソッドで、パスワードリセットに使用したトークンを削除し、パスワードを更新する
        if @user.change_password(params[:user][:password])
          redirect_to login_path, success: "成功しました"
        else
          flash.now[:danger] = "失敗しました"
          render :edit
        end
      end
    end
    

    4. 비밀번호 리셋을 위한 창 만들기


    비밀번호 재설정 신청서


    app/views/password_changes/new.html.erb
    <%= form_with url: password_changes_path, local: true do |f| %>
        <%= f.label :email, "メールアドレス" %>
        <%= f.email_field :email %>
        <%= f.submit "送信する" %>
    <% end %>
    

    암호 재설정에 사용되는 창


    app/views/password_changes/edit.html.erb
          <%= form_with model: @user, url: password_changes_path(@token), local: true do |f| %>
    
              <%= f.label :email %><br>
              <%= @user.email %>
    
              <%= f.label :password %><br>
              <%= f.password_field :password %>
    
              <%= f.label :password_confirmation %><br>
              <%= f.password_field :password_confirmation %>
    
                <%= f.submit %>
          <% end %>
    

    5. 영패는 어떻게 움직이는지, 어떻게 사용하는지


    구령이 리셋되는 일련의 절차에서 영패는 어떻게 사용되는가?

    1. create 작업을 수행할 때 로그 확인

  • 새로 발행된 영패 리셋password_token
  • 비밀번호 리셋용 메일을 보낸 날짜 시간changepassword_email_sent_at
    새 버전이 업데이트되었습니다.
  • User Update All (4.9ms)  UPDATE "users" SET "reset_password_token" = 'h1mJ......2i', 
    "change_password_email_sent_at" = '2020-04-29 17:09:12.464274' WHERE "users"."id" = ?  [["id", 43]]
    

    2. 애플리케이션에서 보낸 메시지 확인


    URL에서 resetpassword_토큰이 묻혔다는 걸 알았어.(h1mj~2i 부분)

    3. 편집 동작으로 디버깅하기


  • id에서 reset -password_토큰의 데이터를 저장했습니다.
    params[:id]의params[:id]로 영패를 획득하고 DB에 저장된 영패와 일치하는지 확인합니다.(업데이트 동작도 마찬가지)
  •     12: def edit
        13: 
        14:   binding.pry
        15:   
     => 16:   @token = params[:id]
        17:   @user = User.load_from_reset_password_token(params[:id])
        18:   return not_authenticated if @user.blank?
        19: end
    
    [1] pry(#<PasswordChangesController>)> params
    => <ActionController::Parameters {"controller"=>"password_changes",
     "action"=>"edit", "id"=>"h1mJZ.....2i"} permitted: false>
    

    참고 자료

  • 공식 사이트
  • sorcery 방법
  • ActionMailer::Base < AbstractController::Base
  • Action Mailer의 기본/Rails 가이드
  • 좋은 웹페이지 즐겨찾기