如何让Devise立即通知用户过期的密码重置令牌?

时间:2014-02-28 02:16:04

标签: ruby-on-rails ruby devise

如果用户连续请求2个密码重置链接,则只有最新的链接有效。

如果用户点击旧版本,则不会立即通知他们该令牌无效。要求他们两次输入新密码。只有在提交提交时,他们才会被告知令牌无效。

是否有更改此行为的标准方法,因此会立即通知用户他们使用了错误的链接?

2 个答案:

答案 0 :(得分:3)

我有点惊讶地发现这是标准行为 - 感谢你提出来!我可能会使用一个继承自Devise::PasswordsController的自定义控制器,只是覆盖:edit。问题是我们正在使用抽象用户(因为此时没有用户实际验证过),因此我们无法针对数据库中的特定令牌进行检查,我们必须检查给定的令牌是否存在。 / p>

class PasswordsController < Devise::PasswordsController
  before_filter :validate_reset_password_token, only: :edit

  private
    def validate_reset_password_token
      recoverable = resource_class.find_by_reset_password_token(params[:reset_password_token])
      redirect_to root_path unless (recoverable && recoverable.reset_password_period_valid?)
    end
end

除非存在传递令牌的用户,否则这将重定向。您可以根据需要处理重定向/错误显示。

最后,在您的路线文件中,更改设计用于密码的控制器:

devise_for :users, :controllers => { passwords: "passwords" }

注意事项:

  • 我没有测试过这个(但我明天可能会考虑一下)。
  • 可能需要考虑一些其他安全问题 - 是否有人可以实际访问随机帐户? (可能不是; Devise使用类似的方法使用reset_password_by_token中的重置标记来定位模型实例)

顺便说一句,没有办法告诉他们他们使用了错误的链接,他们应该点击另一个,因为首先无法正确识别它们,因此无法知道它们已生成另一个有效令牌。

答案 1 :(得分:0)

此问题还有另一种安全解决方案;

class User::PasswordsController < Devise::PasswordsController
  def update
    super do |resource|
      # Jump to super code
      next unless resource.errors.any?
      token_errors = resource.errors.details[:reset_password_token]
      expired_error = token_errors.select { |detail| detail[:error] == :expired }
      # Jump to super code
      next unless expired_error.present?
      message = resource.errors.full_messages_for(:reset_password_token).join(',')
      return redirect_to new_user_password_path, alert: message
    end
  end
end