无法使用自定义密码要求验证 CSRF 令牌的真实性

Can't verify CSRF token authenticity with Custom Password Requirements

我有一个 Rails 5 API 并且我正在设置身份验证。我已经添加了一些自定义密码要求,一切都适用于帐户创建和注销帐户,但每当我尝试登录用户时,我都会收到 Completed 422 Unprocessable Entity 错误以及 Can't verify CSRF token authenticity 消息。当我删除设置自定义密码验证的行时,一切正常。

我已将 protect_from_forgery with: :null_session 添加到我的会话控制器,但没有任何影响。

注册模型:

class Registration < ApplicationRecord
  @username_length = (3..20)

  PASSWORD_CONFIRMATION = /\A
    (?=.{8,})          # Must contain 8 or more characters
    (?=.*\d)           # Must contain a digit
    (?=.*[a-z])        # Must contain a lower case character
    (?=.*[A-Z])        # Must contain an upper case character
    (?=.*[[:^alnum:]]) # Must contain a symbol
  /x

  validates :username, uniqueness: true, length: @username_length
  has_secure_password
  validates :password, format: PASSWORD_CONFIRMATION
  has_secure_token :auth_token

  #used to logout
  def invalidate_token
    self.update_columns(auth_token: nil)
  end

  # makes sure use of built-in auth method bcrypt gives and hashes the password
  # against the password_digest in the db
  def self.validate_login(username, password)
    registration = find_by(username: username)
    if registration && registration.authenticate(password)
      registration
    end
  end
end

会话控制器

class SessionsController < ApiController
  skip_before_action :require_login, only: [:create], raise: false
  protect_from_forgery with: :null_session

  def create
    if registration = Registration.validate_login(params[:username], params[:password])
      allow_token_to_be_used_only_once_for(registration)
      send_token_for_valid_login_of(registration)
    else
      render_unauthorized('Error with your login or password')
    end
  end

  def destroy
    logout
    head :ok
  end

  private

  def send_token_for_valid_login_of(registration)
    render json: { token: registration.auth_token }
  end

  def allow_token_to_be_used_only_once_for(registration)
    registration.regenerate_auth_token
  end

  def logout
    current_registration.invalidate_token
  end
end

注册控制器

class RegistrationController < ApplicationController
  skip_before_action :verify_authenticity_token

  def index; end

  def custom
    user = Registration.create!(registration_params)
    puts "NEW USER #{user}"
    render json: { token: user.auth_token, id: user.id }
  end

  def profile
    user = Registration.find_by_auth_token!(request.headers[:token])
    render json: {
      user: { username: user.username, email: user.email, name: user.name }
    }
  end

  private

  def registration_params
    params.require(:registration).permit(:username, :email, :password, :name)
  end
end

理想情况下,登录应该 return 带有身份验证令牌的 200 消息,就像创建帐户一样。

尝试使用 :with

将验证添加为散列
validates :password, format: {with: PASSWORD_CONFIRMATION}

https://guides.rubyonrails.org/active_record_validations.html#format

我必须调整两件事。首先,我需要在我的注册模型中传递 validations false 标志,所以 has_secure_password 变成了 has_secure_password :validations => false.

其次,我在模型中的 password 上调用了错误的字段名称。通过在 password_digest 而不是 password 上调用 PASSWORD_CONFIRMATION 变量,我的登录开始工作了。