Рельсы 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 приложении, используя эшафот, ничего не меняя, и я столкнулся с той же проблемой, поэтому я думаю, что это не то, что я сделал.

Ответ 1

Думаю, я просто понял это. Я изменил (новый) по умолчанию

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

Ответ 2

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

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

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

Ответ 3

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

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

Ответ 4

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

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

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

class FooController < ApplicationController
  protect_from_forgery except: :index

Ответ 5

Произошла одна и та же проблема. Исправлено, добавив к контроллеру:

      skip_before_filter :verify_authenticity_token, if: :json_request?

Ответ 6

Вы пытались?

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

Ответ 9

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

Таким образом,

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

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

Рельсы 3

skip_before_filter: verify_authenticity_token

Rails 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

Ответ 10

Добавить authenticity_token: true в тег формы

Ответ 11

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

<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 или использовать рельсы, формирующие помощники, а не компрометирующие безопасность и т.д.

Ответ 12

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

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

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

//= require jquery_ujs

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

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

Ответ 13

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

export RAILS_ENV=something_non_test

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

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