Не удается проверить подлинность токена CSRF с помощью пользовательских требований к паролю - PullRequest
0 голосов
/ 09 октября 2019

У меня есть 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

В идеале при входе в систему должно возвращаться сообщение 200 стокен авторизации, как при создании аккаунта.

Ответы [ 2 ]

0 голосов
/ 11 октября 2019

Было две вещи, которые мне пришлось настроить. Во-первых, мне нужно было передать флаг validations false в моей модели регистрации, поэтому has_secure_password стал has_secure_password :validations => false.

Во-вторых, я вызывал неправильное имя поля для password в модели. При вызове переменной PASSWORD_CONFIRMATION для password_digest вместо password мой логин начал работать.

0 голосов
/ 09 октября 2019

Попробуйте добавить проверку в виде хэша с помощью клавиши :with

validates :password, format: {with: PASSWORD_CONFIRMATION}

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

...