rails - "предупреждение: не удается проверить подлинность токена CSRF" для запросов на разработку json
Как я могу получить токен CSRF для передачи с запросом JSON?
Я знаю, что по соображениям безопасности Rails проверяет токен CSRF для всех типов запросов (включая JSON/XML).
я мог бы поставить в мой контроллер skip_before_filter :verify_authenticity_token, но я бы потерял защиту CRSF (не рекомендуется :-) ).
этот аналогичный (все еще не принятый) ответ предлагает
получить маркер с
<%= form_authenticity_token %>
в вопрос как? Нужно ли мне сначала позвонить на любую из моих страниц, чтобы получить маркер, а затем выполнить мою реальную аутентификацию с помощью Devise? Или это информация одноразовая, которую я могу получить с моего сервера, а затем использовать последовательно (пока я вручную не изменю ее на самом сервере)?
11 ответов:
EDIT:
в Rails 4 я теперь использую то, что @genkilabs предлагает в комментарии ниже:
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }который, вместо того, чтобы полностью отключить встроенную безопасность, убивает любой сеанс, который может существовать, когда что-то попадает на сервер без токена CSRF.
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }это отключит проверку CSRF для сообщений/puts json, которые были правильно помечены как таковые.
например, в iOS установите следующее Для вашего NSURLRequest, где "параметры" - это ваши параметры:
[request setHTTPMethod:@"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; [request setValue:@"application/json" forHTTPHeaderField:@"accept"]; [request setHTTPBody:[NSData dataWithBytes:[parameters UTF8String] length:[parameters length]]];
вы можете отправить CSRF токен, после успешного входа в систему, используя пользовательский заголовок.
например, поместите это в свои сеансы#create:
response.headers['X-CSRF-Token'] = form_authenticity_tokenпример заголовка ответа входа в систему, предоставляющего маркер CSRF:
HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Connection: Keep-Alive Content-Length: 35 Content-Type: application/json; charset=utf-8 Date: Mon, 22 Oct 2012 11:39:04 GMT Etag: "9d719d3b9aabd413c3603e04e8a3933d" Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12) Set-Cookie: [cut for readability] X-Csrf-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw= X-Request-Id: 178746992d7aca928c876818fcdd4c96 X-Runtime: 0.169792 X-Ua-Compatible: IE=Edgeэтот токен действителен до тех пор, пока вы не войдете в систему снова или (выход из системы, если вы поддерживаете это через свой API). Клиент может извлечь и сохранить маркер из заголовков ответов входа в систему. Затем каждый запрос POST / PUT / DELETE должен установить заголовок X-CSRF-Token со значением, полученным при входе в систему.
пример заголовков сообщений с токеном CSRF:
POST /api/report HTTP/1.1 Accept: application/json Accept-Encoding: gzip, deflate, compress Content-Type: application/json; charset=utf-8 Cookie: [cut for readability] Host: localhost:3000 User-Agent: HTTPie/0.3.0 X-CSRF-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=документы: form_authenticity_token
действительно самый простой способ. Не беспокойтесь об изменении заголовков.
убедитесь, что у вас есть:
<%= csrf_meta_tag %>в своем
layouts/application.html.erbпросто сделайте скрытое поле ввода так:
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>"/>или если вы хотите сообщение jQuery ajax:
$.ajax({ type: 'POST', url: "<%= someregistration_path %>", data: { "firstname": "text_data_1", "last_name": "text_data2", "authenticity_token": "<%= form_authenticity_token %>" }, error: function( xhr ){ alert("ERROR ON SUBMIT"); }, success: function( data ){ //data response can contain what we want here... console.log("SUCCESS, data="+data); } });в основном, когда вы публикуете свои данные json, просто добавьте допустимое поле authenticity_token в
postданные и предупреждение должны уйти...
Я решил эту ошибку следующим образом:
class ApplicationController < ActionController::Base protect_from_forgery skip_before_action :verify_authenticity_token, if: :json_request? protected def json_request? request.format.json? end endисточник: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
Что беспокоит, так это то, что в Rails 3.2.3 мы теперь получаем предупреждение CSRF в производстве.журнал, но сообщение не терпит неудачу! Я хочу, чтобы он потерпел неудачу, поскольку он защищает меня от атак. И вы можете добавить токен csrf с помощью jquery перед фильтром btw:
я использовал ниже. Используя включить? поэтому, если тип контента-application/json;charset=utf-8, то он все еще работает.
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format.include? 'application/json' }
ответ - это лучше.
вы можете сохранить проверку CSRF-токена без дополнительных усилий (токен добавляется) перед отправкой любого XMLHttpRequest. Нет JQuery, нет ничего просто скопировать/вставить и обновить.
просто добавьте этот код.
(function() { var send = XMLHttpRequest.prototype.send, token = $('meta[name=csrf-token]').attr('content'); XMLHttpRequest.prototype.send = function(data) { this.setRequestHeader('X-CSRF-Token', token); return send.apply(this, arguments); }; }());
У меня была такая же проблема со следующей версией Rails:
драгоценный камень 'рельсы', :Git с помощью Git => '://гитхабе.ком/рельсы/рельсы.ГИТ', :ветка => '3-2-стабильный'Я обновился до 3.2.2, и теперь все отлично работает для меня. :)
драгоценный камень 'рельсы', '3.2.2'
я столкнулся с той же проблемой сегодня вечером. Причина, по которой это происходит, заключается в том, что при входе в последний CSRF-токен больше не действителен. То, что я сделал:
$("meta[name=csrf-token]").attr('content', '<%= form_authenticity_token %>');в вашем приложении / views/devise/sessions / create.js.рубидий.теперь у него есть действительный csrf-токен :) Я надеюсь, что это поможет
также для разработки / тестового режима.
protect_from_forgery with: :exception unless %w(development test).include? Rails.envэто предупреждение показывает, потому что вы используете
:null_session, в Rails 4.1 он работает по умолчанию, если нетwith:параметры, указанные.protect_from_forgery
Это не ошибка. Он должен быть проверен на каждом запросе без получения. https://github.com/rails/rails/issues/3041
Comments