Rails 4 Authenticity Token

2019-01-04 15:15发布

I was working on a new Rails 4 app (on Ruby 2.0.0-p0) when I ran into some authenticity token problems.

While writing a controller that responds to json (using the respond_to class method), I got to the create action I started getting ActionController::InvalidAuthenticityToken exceptions when I tried to create a record using curl.

I made sure I set -H "Content-Type: application/json" and I set the data with -d "<my data here>" but still no luck.

I tried writing the same controller using Rails 3.2 (on Ruby 1.9.3) and I got no authenticity token problems whatsoever. I searched around and I saw that there were some changes with authenticity tokens in Rails 4. From what I understand, they are no longer automatically inserted in forms anymore? I suppose this is somehow affecting non-HTML content types.

Is there any way to get around this without having to request a HTML form, snatching the authenticity token, then making another request with that token? Or am I completely missing something that's completely obvious?

Edit: I just tried creating a new record in a new Rails 4 app using a scaffold without changing anything and I'm running into the same problem so I guess it's not something I did.

13条回答
再贱就再见
2楼-- · 2019-01-04 16:00

All my tests were working fine. But for some reason I had set my environment variable to non-test:

export RAILS_ENV=something_non_test

I forgot to unset this variable because of which I started getting ActionController::InvalidAuthenticityToken exception.

After unsetting $RAILS_ENV, my tests started working again.

查看更多
够拽才男人
3楼-- · 2019-01-04 16:02

Came across the same problem. Fixed it by adding to my controller:

      skip_before_filter :verify_authenticity_token, if: :json_request?
查看更多
别忘想泡老子
4楼-- · 2019-01-04 16:03

Adding the following line into the form worked for me:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
查看更多
萌系小妹纸
5楼-- · 2019-01-04 16:04

I don't think it's good to generally turn off CSRF protection as long as you don't exclusively implement an API.

When looking at the Rails 4 API documentation for ActionController I found that you can turn off forgery protection on a per controller or per method base.

For example to turn off CSRF protection for methods you can use

class FooController < ApplicationController
  protect_from_forgery except: :index
查看更多
太酷不给撩
6楼-- · 2019-01-04 16:09

Did you try?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
查看更多
霸刀☆藐视天下
7楼-- · 2019-01-04 16:12

When you define you own html form then you have to include authentication token string ,that should be sent to controller for security reasons. If you use rails form helper to generate the authenticity token is added to form as follow.

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
  </div>
    ...
</form>

So the solution to the problem is either to add authenticity_token field or use rails form helpers rather then compromising security etc.

查看更多
登录 后发表回答