Can I use curl or curb to POST to a form that uses rails' Cross-site request forgery protection?

StackOverflow https://stackoverflow.com/questions/10381261

  •  04-06-2021
  •  | 
  •  

I have a simple rails webpage where a user enters in a few textfields and uploads a picture. Rails then stores the picture and updates the databases on the server. It works fine.

However, I also need a script on another computer to update the web page occasioanlly using the curl/curb libraries. When i try to do that, though, I get this error:

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)

When I look closer, it seems that rails puts in a hidden field called "authenticity_token" whenever it creates a form:

<form action="/headshots/single" enctype="multipart/form-data" method="post">
<input name="authenticity_token" type="hidden" value="798b514826513c881613a0c18b52839489a12181" />
. . .
</form>

The curb script won't work because it doesn't have the "authenticity_token" thing. Is there any way around this? Maybe make another webpage that does the same thing, but just for my curb script?

有帮助吗?

解决方案

The hidden input is there to prevent Cross-Site Request Forgery. You can't make a post to a rails action which is so protected without first getting the form and extracting the hidden authenticity_token parameter. curl isn't clever enough to do this on its own.

You have two options:

  1. turn off the CSRF protection by removing the call to protect_from_forgery from your controller(s). Bad Idea.
  2. run one request to get the form, use a quick-and-dirty regex to get the paremeter, say

    /name="authenticity_token".*value="([^"]+)"/

    and then run another request posting that value for authenticity_token. It's brittle and it might make people hate you but it will work.

  3. Use something more sophisticated than curl to make the necessary request for the form and the successive submission. Mechanize appears to be the de facto standard.

其他提示

How to submit a form with mechanize:

Mechanize.new.get('url_with_form').forms[0].tap{|f| f.field = 'value'}.submit
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top