rails - InvalidAuthenticityToken for json/xml requests

后端 未结 6 1298
清歌不尽
清歌不尽 2020-12-15 05:08

For some reason I\'m getting an InvalidAuthenticityToken when making post requests to my application when using json or xml. My understanding is that rails should require an

相关标签:
6条回答
  • 2020-12-15 05:25

    With protect_from_forgery enabled, Rails requires an authenticity token for any non-GET requests. Rails will automatically include the authenticity token in forms created with the form helpers or links created with the AJAX helpers--so in normal cases, you won't have to think about it.

    If you're not using the built-in Rails form or AJAX helpers (maybe you're doing unobstrusive JS or using a JS MVC framework), you'll have to set the token yourself on the client side and send it along with your data when submitting a POST request. You'd put a line like this in the <head> of your layout:

    <%= javascript_tag "window._token = '#{form_authenticity_token}'" %>
    

    Then your AJAX function would post the token with your other data (example with jQuery):

    $.post(url, {
        id: theId,
        authenticity_token: window._token
    });
    
    0 讨论(0)
  • 2020-12-15 05:27

    To add to Fernando's answer, if your controller responds to both json and html, you can use:

          skip_before_filter :verify_authenticity_token, if: :json_request?
    
    0 讨论(0)
  • 2020-12-15 05:28

    Another way is to avoid verify_authenticity_token using skip_before_filter in your Rails App:

    skip_before_action :verify_authenticity_token, only: [:action1, :action2]
    

    This will let curl to do its job.

    0 讨论(0)
  • 2020-12-15 05:30

    Adding up to andymism's answer you can use this to apply the default inclusion of the TOKEN in every POST request:

    $(document).ajaxSend(function(event, request, settings) {
        if ( settings.type == 'POST' ||  settings.type == 'post') {
            settings.data = (settings.data ? settings.data + "&" : "")
                + "authenticity_token=" + encodeURIComponent( window._token );
        }
    });
    
    0 讨论(0)
  • 2020-12-15 05:33

    I had a similar situation and the problem was that I was not sending through the right content type headers - I was requesting text/json and I should have been requesting application/json.

    I used curl the following to test my application (modify as necessary):

    curl -H "Content-Type: application/json" -d '{"person": {"last_name": "Lambie","first_name": "Matthew"}}' -X POST http://localhost:3000/people.json -i
    

    Or you can save the JSON to a local file and call curl like this:

    curl -H "Content-Type: application/json" -v -d @person.json -X POST http://localhost:3000/people.json -i
    

    When I changed the content type headers to the right application/json all my troubles went away and I no longer needed to disable forgery protection.

    0 讨论(0)
  • 2020-12-15 05:49

    This is the same as @user1756254's answer but in Rails 5 you need to use a bit more different syntax:

    protect_from_forgery unless: -> { request.format.json? }
    

    Source: http://api.rubyonrails.org/v5.0/classes/ActionController/RequestForgeryProtection.html

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