If I create a brand new Rails application (using Rails 3.0.9) and knock up a quick bit of scaffolding as follows:
$ rails new testing
$ rails g scaffold thing name:string
Then app/controllers/application_controller.rb contains a "protect_from_forgery" by default, so it should check the authenticity_token during a POST create. At least, that's my understanding.
Why then, does this line successfully create a new Thing, without supplying the token.
$ curl -F "thing[name]=abc123" http://localhost:3000/things
The log entry says:
Started POST "/things" for 127.0.0.1 at 2011-07-05 08:29:18 +0100
Processing by ThingsController#create as
Parameters: {"thing"=>{"name"=>"abc123"}}
AREL (0.3ms) INSERT INTO "things" ("name", "created_at", "updated_at") VALUES ('abc123', '2011-07-05 07:29:18.484457', '2011-07-05 07:29:18.484457')
Redirected to http://localhost:3000/things/18
Completed 302 Found in 89ms
I can also do this to delete records:
$ curl -X DELETE http://localhost:3000/things/18
The same thing happens in production mode. Doesn't t开发者_如何学运维his leave my application open to CSRF?
If you pass invalid CSRF token or send request without it, Rails will nullify session, so protect_form_forgery
is useless if your application could be accessed by everyone.
But it will save your application from CSRF attack if you have session-based authentication system.
More info: How does Rails CSRF protection work?
精彩评论