【问题标题】:Rails devise reset password token doesn't get clearRails 设计重置密码令牌不清楚
【发布时间】:2023-03-04 13:13:02
【问题描述】:

我正在使用设计 gem。当用户单击忘记密码链接时,设计在邮件中发送重置密码令牌。用户点击链接并通过输入新密码并确认新密码来重置密码。

当我再次点击相同的邮件链接时,它再次允许用户以与上述相同的方式重置密码。

现在,我希望重置密码令牌在使用后立即清除。因此,当您从旧邮件中关注先前使用的发送链接时,他必须收到“无效令牌”的消息

我该怎么做?

提前致谢。

【问题讨论】:

  • 您使用的是哪个版本的 Rails 和设计?
  • Rails 3.2.13 设计 3.1.0

标签: ruby-on-rails ruby ruby-on-rails-3 devise


【解决方案1】:

比建议的更简单、更安全的解决方案:

创建你自己的密码控制器,我选择将它放在 controllers/auth 下

controllers/auth/passwords_controller.rb

class Auth::PasswordsController < Devise::PasswordsController

  def update
    super do |resource|
      if resource.reset_password_token_changed? and resource.reset_password_token_was.nil?
        resource.reset_password_token = nil 
      end
    end
  end

end

这解决了许多问题,例如 papertrail,并且无论如何保存对 DB 的访问

【讨论】:

    【解决方案2】:

    您可以尝试以下任一方法

     # reset_password_within = 1.day and reset_password_sent_at = today
    reset_password_period_valid?   # returns true
    
    # reset_password_within = 5.days and reset_password_sent_at = 4.days.ago
    reset_password_period_valid?   # returns true
    
    # reset_password_within = 5.days and reset_password_sent_at = 5.days.ago
    reset_password_period_valid?   # returns false
    
    # reset_password_within = 0.days
    reset_password_period_valid?   # will always return false
    

    或者您可以调用实例方法,例如清除重置密码令牌或通过调用 clear_reset_password_tokenafter_password_reset 方法。

    【讨论】:

    • 如何以及在哪里可以使用 reset_password_period_valid?显示消息“令牌无效”的方法,如果令牌有效,用户将继续输入新密码。你能不能给出清晰的愿景。我需要覆盖密码控制器吗?
    【解决方案3】:

    我认为,如果您在用户模型或设计已使用的模型中执行以下操作,此 hack 应该会更容易。

    class YourModel < ActiveRecord::Base
      ...
         def after_password_reset
              self.clear_reset_password_token if not (self.reset_password_token.nil? and self.reset_password_sent_at.nil?)
         end
    end
    

    我建议不要使用您的控制器进行业务操作。这个 after_password_reset 密码用于在设计中调用 clear_reset_password 令牌。这是参考: https://github.com/plataformatec/devise/blob/master/lib/devise/models/recoverable.rb#L39

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      我通过在应用程序中覆盖 Devise::PasswordsController 实现了上述目标。

      在 PasswordController#edit 操作上设计句柄重置密码。

      在编辑时,我检查了重置密码令牌是否有效。如果它有效,我允许用户重置密码,否则将用户重定向到“密码令牌无效消息”的登录页面。

      对于设计 3.0

      class Users::PasswordsController < Devise::PasswordsController
        def edit
          self.resource = resource_class.find_or_initialize_with_error_by(:reset_password_token,       params[:reset_password_token])
          if !resource.errors.empty?
            flash[:alert] = "Password token is invalid"
            redirect_to new_session_path(resource_name)
          end 
        end
      end
      

      对于设计 3.1

      class Users::PasswordsController < Devise::PasswordsController
        def edit
          original_token       = params[:reset_password_token]
          reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
          self.resource = resource_class.find_or_initialize_with_error_by(:reset_password_token, reset_password_token)
          if !resource.errors.empty?
            flash[:alert] = "Password token is invalid"
            redirect_to new_session_path(resource_name)
          end
        end
      end
      

      【讨论】:

      • 您可以覆盖此after_password_reset 方法以在您的模型上执行此操作。您不需要为此生成控制器。
      猜你喜欢
      • 2017-05-09
      • 2014-01-27
      • 2016-02-22
      • 2020-06-03
      • 1970-01-01
      • 2011-08-19
      • 2020-07-13
      • 2011-11-29
      • 1970-01-01
      相关资源
      最近更新 更多