Rails 4 Токен Подлинности

Я работал над новым приложением Rails 4 (на Ruby 2.0.0-p0), когда столкнулся с некоторыми проблемами с токенами подлинности.

При написании контроллера, который отвечает на JSON (используя respond_to метод класса), я добрался до create действие, которое я начал получать ActionController::InvalidAuthenticityToken исключения, когда я пытался создать запись, используя curl,

Я убедился, что я установил -H "Content-Type: application/json" и я установил данные с -d "<my data here>" но все равно не повезло.

Я попытался написать тот же контроллер с использованием Rails 3.2 (на Ruby 1.9.3), и у меня не возникло проблем с токеном подлинности. Я искал вокруг и увидел, что в Rails 4 произошли некоторые изменения с токенами аутентичности. Насколько я понимаю, они больше не вставляются автоматически в формы? Я предполагаю, что это как-то влияет на не-HTML типы контента.

Есть ли способ обойти это без необходимости запрашивать HTML-форму, перехватывая токен аутентификации, а затем отправляя другой запрос с этим токеном? Или я полностью упускаю что-то совершенно очевидное?

Изменить: Я только что попытался создать новую запись в новом приложении Rails 4, используя скаффолд, ничего не меняя, и я столкнулся с той же проблемой, поэтому я думаю, что это не то, что я сделал.

13 ответов

Решение

Я думаю, что я только что понял это. Я изменил (новый) по умолчанию

protect_from_forgery with: :exception

в

protect_from_forgery with: :null_session

согласно комментарию в ApplicationController,

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

Вы можете увидеть разницу, посмотрев на источник request_forgery_protecton.rbили, более конкретно, следующие строки:

В Rails 3.2:

# This is the method that defines the application behavior when a request is found to be unverified.
# By default, \Rails resets the session when it finds an unverified request.
def handle_unverified_request
  reset_session
end

В Rails 4:

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

Который будет называть следующее:

def handle_unverified_request
  raise ActionController::InvalidAuthenticityToken
end

Вместо того, чтобы отключить защиту csrf, лучше добавить следующую строку кода в форму

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

и если вы используете form_for или form_tag для генерации формы, то она автоматически добавит вышеуказанную строку кода в форму

Добавление следующей строки в форму работало для меня:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

Я не думаю, что хорошо вообще отключать защиту CSRF, если вы не используете исключительно API.

Просматривая документацию по Rails 4 API для ActionController, я обнаружил, что вы можете отключить защиту от подделки для каждого контроллера или для каждого метода.

Например, чтобы отключить защиту CSRF для методов, которые вы можете использовать

class FooController < ApplicationController
  protect_from_forgery except: :index

Наткнулся на ту же проблему. Исправлено, добавив в мой контроллер:

      skip_before_filter :verify_authenticity_token, if: :json_request?

Ты пробовал?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }

В этом официальном документе рассказывается о том, как правильно отключить защиту от мошенничества для API http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html

Это функция безопасности в Rails. Добавьте эту строку кода в форму:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

Документацию можно найти здесь: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html

Эти функции были добавлены в целях безопасности и защиты от подделки.
Однако, чтобы ответить на ваш вопрос, вот некоторые материалы. Вы можете добавить эти строки после вашего имени контроллера.

Вот так,

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

Вот несколько строк для разных версий рельсов.

Рельсы 3

skip_before_filter: verify_authenticity_token

Рельсы 4:

skip_before_action: verify_authenticity_token


Если вы намереваетесь отключить эту функцию безопасности для всех подпрограмм контроллера, вы можете изменить значение protect_from_forgery на :null_session в вашем файле application_controller.rb.

Вот так,

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
end

Добавлять authenticity_token: true к тегу формы

Если вы используете jQuery с rails, будьте осторожны, разрешив вход в методы без проверки токена подлинности.

JQuery-UJS может управлять токенами для вас

Он должен быть уже в составе гема jquery-rails, но вам может понадобиться включить его в application.js с

//= require jquery_ujs

Это все, что вам нужно - теперь ваш Ajax-вызов должен работать

Для получения дополнительной информации см.: https://github.com/rails/jquery-ujs

Когда вы определяете свою собственную html-форму, вы должны включить строку токена аутентификации, которая должна быть отправлена ​​на контроллер по соображениям безопасности. Если вы используете rails form helper для генерации токена подлинности, он добавляется в форму следующим образом.

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
  </div>
    ...
</form>

Таким образом, решение проблемы состоит в том, чтобы либо добавить поле authenticity_token, либо использовать помощники по рельсам, а не ставить под угрозу безопасность и т. Д.

Все мои тесты работали нормально. Но по какой-то причине я установил переменную среды non-test:

export RAILS_ENV=something_non_test

Я забыл сбросить эту переменную, из-за которой я начал получать ActionController::InvalidAuthenticityToken исключение.

После сброса $RAILS_ENVмои тесты снова начали работать.

Другие вопросы по тегам