操作前回调方法多次重定向,同时强制用户在 rails 中更改密码

A Before action callback method redirects multiple times while forcing the user to change password in rails

一个场景需要,当用户登录时,如果没有更改密码,他应该redirect_to更改密码的路径我尝试了以下方式

1)
    class ApplicationController < ActionController::Base
    before_action :check_password, if: :current_user
     def check_password 
      if current_user.present? && 
         current_user.try(:created_at).try(:to_datetime) == 
         current_user.try(:password_changed_at).try(:to_datetime)
        redirect_to change_password_admin_user_path(current_user)
      end
     end
    end
2)    
class Admin::UsersController < ApplicationController
  skip_before_action :check_password, only: [:change_password, :update_password]
     
  def change_password
    @user = User.find(params[:id])
  end
    
  def update_password
   @user = User.find(params[:id])
   if @user.valid_password?(params[:old_password])
     if @user.update_attributes(password: params[:new_password], password_confirmation: params[:reenter_password])
      flash[:notice] = 'Password changed successfully, please login with new password'
      redirect_to new_user_session_path and return
    else
      flash[:alert] = @user.errors.full_messages.join(', ')
    end
  else
   flash[:alert] = "Old password you've entered is invalid"
  end
  redirect_to change_password_admin_user_path(@user.id)
 end
end
 
3)   
class Admin::SessionsController < Devise::SessionsController
 skip_before_action :check_password, only: :destroy
end

我强制用户更改密码,但它多次抛出重定向错误

1)
    class ApplicationController < ActionController::Base
    before_action :check_password, if: :current_user # this is why you're getting multiple redirect.
     def check_password 
      if current_user.present? && 
         current_user.try(:created_at).try(:to_datetime) == 
         current_user.try(:password_changed_at).try(:to_datetime)
        redirect_to change_password_admin_user_path(current_user)
      end
     end
    end

所以,请不要这样使用。

如何将 check_password 方法移动到另一个控制器?

例如

class DashboardController < ActionController::Base
  def dashboard
    if current_user.present? && 
      current_user.try(:created_at).try(:to_datetime) == 
      current_user.try(:password_changed_at).try(:to_datetime)
      redirect_to change_password_admin_user_path(current_user)
    end
  end
end

此外,除非他更改了密码,否则不要显示任何菜单。

根据您的评论,您正在使用 devise-security gem, so you can use the method need_change_password! (which will clear password_changed_at) right after the user sign-up, so that the devise hook password_expirable 将检查并强制新用户更改通过,您无需自己处理此逻辑。