rails - “WARNING: Can't verify CSRF token authenticity” for json devise requests

前端 未结 10 2117
终归单人心
终归单人心 2020-11-27 10:11

How can I retrieve the CSRF token to pass with a JSON request?

I know that for security reasons Rails is checking the CSRF token on all the request types (including

相关标签:
10条回答
  • 2020-11-27 10:27

    Indeed simplest way. Don't bother with changing the headers.

    Make sure you have:

    <%= csrf_meta_tag %>
    

    in your layouts/application.html.erb

    Just do a hidden input field like so:

    <input name="authenticity_token" 
           type="hidden" 
           value="<%= form_authenticity_token %>"/>
    

    Or if you want a jquery ajax post:

    $.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);
        }
    });
    

    Basically when you post your json data just add a valid authenticity_token field to the post data and the warning should go away...

    0 讨论(0)
  • 2020-11-27 10:28

    EDIT:

    In Rails 4 I now use what @genkilabs suggests in the comment below:

    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }

    Which, instead of completely turning off the built in security, kills off any session that might exist when something hits the server without the CSRF token.


    skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }

    This would turn off the CSRF check for json posts/puts that have properly been marked as such.

    For example, in iOS setting the following to your NSURLRequest where "parameters" are your parameters:


    [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]]];
    
    0 讨论(0)
  • 2020-11-27 10:29

    Also for development/test mode.

    protect_from_forgery with: :exception unless %w(development test).include? Rails.env
    

    This warning shows because you are using :null_session, in Rails 4.1 it works by default if no with: options specified.

    protect_from_forgery
    
    0 讨论(0)
  • 2020-11-27 10:30

    I have used the below. Using include? so if the content type is application/json;charset=utf-8 then it is still working.

    protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format.include? 'application/json' }
    
    0 讨论(0)
  • 2020-11-27 10:37

    What's worrying is that in Rails 3.2.3 we now get the CSRF warning in production.log but the post does not fail! I want it to fail as it protects me from attacks. And you can add the csrf token with jquery before filter btw:

    http://jasoncodes.com/posts/rails-csrf-vulnerability

    0 讨论(0)
  • 2020-11-27 10:38

    I ran into the same issue tonight. The reason that happens is because when you sign in the last csrf-token is no longer valid. What I did was: $("meta[name=csrf-token]").attr('content', '<%= form_authenticity_token %>'); in your app/views/devise/sessions/create.js.rb.

    Now it does have a valid csrf-token :) I hope it helps

    0 讨论(0)
提交回复
热议问题