Techioz Blog

無限ループを考案する :require_no_authentication としてフィルター チェーンが停止する

概要

Ruby on Rails 6 と Devise を使用していると奇妙な問題が発生します。サインインまたはサインアウト後、アプリは root_path にリダイレクトされず、無限ループになります。 root_path は認証を必要としないため、リダイレクトすべきではありません。

エラーログ:

ルート:

devise_for :users, 
path: "utilisateurs",
controllers: { 
    sessions: 'users/sessions', 
    registrations: 'users/registrations', 
    passwords: 'users/passwords',
    confirmations: 'users/confirmations'
},
:path_names => { :sign_in => 'connexion', :sign_up => 'inscription', :sign_out => 'deconnexion', password: 'retrouver_mot_de_passe', edit: 'finaliser-inscription' }

ユーザーモデル:

class User < ApplicationRecord
    attr_accessor :skip_password_validation
    before_validation :check_pseudo, only: [:create, :update]
    validates :pseudo, presence: true
    validates :email, 
                        format: { with: URI::MailTo::EMAIL_REGEXP },
                        presence: true,
                        uniqueness: true

    has_secure_token

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable, :trackable

    has_many :comments, dependent: :nullify
    has_one :author, dependent: :nullify
    has_one :blitz_score, :dependent => :destroy
    has_one :blitz_conjugaison_score, :dependent => :destroy
    has_many :quiz_scores, :dependent => :destroy
    has_many :dictee_scores, :dependent => :destroy
    has_many :crossword_scores, :dependent => :destroy
    has_many :track_subscribers, :dependent => :destroy

    def authenticatable_salt
    return super unless session_token

    "#{super}#{session_token}"
  end

  def invalidate_all_sessions!
    update_attribute(:session_token, SecureRandom.hex)
  end

    protected

    def check_pseudo
        unless self.pseudo.present?
            self.pseudo = self.email.split("@")[0] if self.email.present?
        end
    end

    def password_required?
    return false if skip_password_validation
    super
  end
end

アカウントの作成にパスワードは必要ないことに注意してください。訪問者は最初にメールアドレスを入力し、アカウントを確認した後に擬似パスワードとパスワードを入力します。

セッションコントローラー:

class Users::SessionsController < Devise::SessionsController
    layout 'blank'

  protected
    
    def after_sign_in_path_for(resource_or_scope)
        root_path
    end 
    
    def after_sign_out_path_for(resource_or_scope)
        root_path
    end
end

イニシャライザを考案します:

Devise.setup do |config|

  require 'devise/orm/active_record'

  config.case_insensitive_keys = [:email]

  config.strip_whitespace_keys = [:email]

  config.skip_session_storage = [:http_auth]

  config.stretches = Rails.env.test? ? 1 : 12

  config.reconfirmable = false

  config.expire_all_remember_me_on_sign_out = true

  config.password_length = 6..128

  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/

  config.reset_password_within = 24.hours

  config.navigational_formats = ['*/*', :html]

  config.sign_out_via = :delete
end

開発構成:

Rails.application.configure do
  config.cache_classes = false

  config.eager_load = false

  config.consider_all_requests_local = true

  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = false
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  config.active_storage.service = :local

  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false

    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
    config.action_mailer.delivery_method = :mailjet

  config.active_support.deprecation = :log

  config.active_record.migration_error = :page_load

  config.active_record.verbose_query_logs = true

  config.assets.debug = true

  config.assets.quiet = true

  config.file_watcher = ActiveSupport::EventedFileUpdateChecker
    
    config.active_job.queue_adapter = :sidekiq

    config.i18n.default_locale = :fr

    config.after_initialize do
        Bullet.enable = true
        Bullet.bullet_logger = true
        Bullet.unused_eager_loading_enable = false
        Bullet.raise = false
    end
end

次のことを試しましたが成功しませんでした。

これが問題の原因であるかどうかはわかりませんが、他のいくつかの Rails アプリに取り組んでいます。 Rails を使用してそれらを個別に起動し、サーバーは localhost:3000 にあります。おそらくこれによりセッションが台無しになる可能性がありますか?

助けてくれてありがとう。

解決策

結局、問題は PWA 実装の service-worker.js に関連していました。

どういうわけか、Devise は service-worker.js にリダイレクトしていたため、無限リダイレクト ループが発生していました。