Сценарий скрепки скрепки, вызывающие проблемы с проверкой токена CSRF

У меня есть приложение Rails 3.1, в котором используется копия paperclip (v 3.4.0). В двух словах. У меня есть модель истории и модель публикации. В истории может быть много сообщений.

#story.rb

class Story < ActiveRecord::Base

  attr_accessible :title, :user_id, :username, :posts_attributes

  belongs_to    :user
  has_many      :posts, :dependent  =>  :destroy,
                      :order => "created_at DESC"

  accepts_nested_attributes_for :posts, :reject_if => lambda { |t| t['contents'].nil? }

end

#post.rb

class Post < ActiveRecord::Base

  attr_accessible :contents, :photo, :dimensions

  belongs_to    :story, :touch => true
  belongs_to    :user, :touch => true

  has_attached_file :photo, 
                    :styles => { 
                      :medium => { :geometry => "400x400>" },
                      :thumb => { :geometry => "100x100>" },
                    },
                    :processors => [:thumbnail],
                    :storage => :s3,
                    :s3_credentials => "#{Rails.root.to_s}/config/s3.yml",
                    :path => "/:style/:id/:filename"


  before_save   :extract_dimensions

  serialize   :dimensions

  validates   :contents,  :presence   => true,
                      :length         => {  :maximum => 399,
                                        :minimum => 5 } 
  validates   :user_id,   :presence => true

  validates_attachment_content_type :photo, 
    :content_type => ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'],
    :message => "Sorry, we don't support that type of image format"

end

Как вы можете видеть, сообщения могут иметь прикрепление фотографий. Я использую paperclip для управления этими вложениями.

Я генерирую форму, которая POSTs эти сообщения динамически на клиенте с javascript/jquery. Моя проблема в этом., Если сообщение НЕ содержит прикрепленное фото, все работает отлично. ЕСЛИ, ОДНАКО, У ПОСТ-ТАСС ПРИЛОЖЕНИЕ ФОТО, я получаю следующее сообщение об ошибке, и сообщение не отправляется:

WARNING: Can't verify CSRF token authenticity
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 61 LIMIT 1
   (0.3ms)  BEGIN
   (0.2ms)  COMMIT
Completed 401 Unauthorized in 238ms

В результате мои данные сеанса уничтожены, и я даже не вижу заголовки запросов с Firebug. Запрос запроса просто не отображается в firebug.

Теперь, что неудивительно, я могу обойти эту проблему со следующим в PostController:

skip_before_filter :verify_authenticity_token, :only => [:create]

Но я не хочу отказываться от этой безопасности. Я также попытался добавить заголовок CSRF в мою форму через js/jquery:

jQuery.ajaxSetup({ 
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-          
            token"]').attr('content'));
  }
});

Но это не решает проблему, и, как я сказал выше, я даже не вижу данные заголовка запроса, чтобы увидеть заголовок.

Может ли кто-нибудь придумать причину, по которой скрепка запускает проблему?

Ответ 1

Я знаю, что прошло некоторое время с тех пор, как я впервые разместил вышеупомянутый вопрос, но люди все еще находят его в своих поисках, поэтому я решил, что обновляю все с ответом.

Проблема, о которой я говорил выше, не имела ничего общего с Paperclip. Форма отправляется без токена csrf, потому что я использую remotipart.js для обработки представлений форм с файловыми вложениями. Remotipart разрешает ajax-подобную передачу формы путем копирования данных формы в i-фрейм, который затем делает обычную (т.е. Не-ajax) подачу, пока ваш сайт остается активным. См. в этой статье для более подробного описания загрузки файла ajax через i-frame.

В предыдущих версиях remotipart токен csrf не был скопирован в форму, отправленную i-фреймом. Хорошие люди, поддерживающие remotipart, теперь исправили этот недостаток. Вы можете найти исправление здесь

Ответ 2

$.ajaxSetup({
    beforeSend: function(xhr) {
        xhr.setRequestHeader('X-CSRF-Token',
                             $('meta[name="csrf-token"]').attr('content'));
    }
});

в js

и в макете

<%= csrf_meta_tags %>
Файл

должен быть достаточным, чтобы заставить его работать.

в противном случае вы можете использовать jquery-rails gem, который обрабатывает токен CSRF