Paperclip gem triggering CSRF token verification problems
Asked Answered
D

3

11

I have a Rails 3.1 app that makes use of the paperclip gem (v 3.4.0). In a nutshell. I have a story model and a post model. A story can have many posts.

#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

As you can see, posts may have a photo attachment. I use paperclip to manage these attachments.

I generate the form that POSTs these posts dynamically on the client with javascript/jquery. My problem is this . . . If the post does NOT include a photo attachment everything works perfectly. IF, HOWEVER, A POST HAS A PHOTO ATTACHMENT, I receive the following error message and the post doesn't POST:

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

As a result, my session data is destroyed, and I can't even see the request headers with Firebug. The put request simply does not appear in firebug.

Now, not surprisingly, I can get around this problem with the following in the PostController:

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

But I don't want to give up this security. I have also tried adding the CSRF header to my form via js/jquery:

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

But that doesn't solve the problem, and as I said above, I can't even see the request header data to see the header.

Can anyone come-up with a reason why paperclip triggers the problem?

Dicky answered 7/3, 2013 at 0:55 Comment(0)
D
1

I know that it's been a while since I first posted the above question, but people are still finding it in their searches, so I thought I'd update things with an answer.

The problem I discussed above had nothing to do with Paperclip. The form is being submitted without a csrf token because I am using remotipart.js to handle the submission of forms that have file attachments. Remotipart enables an ajax-like submission of a form by copying the form data into an i-frame, which then makes a normal (i.e., non-ajax) submission while your site stays active. See this article for a more detailed description of ajax file uploads via i-frame.

In previous versions of remotipart the csrf token was not copied over to the form being submitted by the i-frame. The good people supporting remotipart have now fixed this shortcoming. You can find the fix here

Dicky answered 14/11, 2013 at 5:36 Comment(0)
H
0
$.ajaxSetup({
    beforeSend: function(xhr) {
        xhr.setRequestHeader('X-CSRF-Token',
                             $('meta[name="csrf-token"]').attr('content'));
    }
});

in js

and in the layout

<%= csrf_meta_tags %>

file should be enough to make it working.

otherwise you can use jquery-rails gem that handles CSRF token

Hyperextension answered 7/6, 2013 at 3:9 Comment(1)
mostly you just need <%= csrf_meta_tags %> in your layout - in the <head> section.Penicillate
O
0

This is what you need to solve the problem:

https://github.com/JangoSteve/remotipart

Osteotome answered 9/1, 2017 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.