Ruby-on-rails Rails:发出 POST 请求时无法验证 CSRF 令牌的真实性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35181340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails: Can't verify CSRF token authenticity when making a POST request
提问by cqcn1991
I want to make POST requestto my local dev, like this:
我想为POST request我的本地开发人员制作,如下所示:
HTTParty.post('http://localhost:3000/fetch_heroku',
:body => {:type => 'product'},)
However, from the server console it reports
但是,它从服务器控制台报告
Started POST "/fetch_heroku" for 127.0.0.1 at 2016-02-03 23:33:39 +0800
ActiveRecord::SchemaMigration Load (0.0ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by AdminController#fetch_heroku as */*
Parameters: {"type"=>"product"}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms
Here is my controller and routes setup, it's quite simple.
这是我的控制器和路由设置,非常简单。
def fetch_heroku
if params[:type] == 'product'
flash[:alert] = 'Fetch Product From Heroku'
Heroku.get_product
end
end
post 'fetch_heroku' => 'admin#fetch_heroku'
I'm not sure what I need to do? To turn off the CSRF would certainly work, but I think it should be my mistake when creating such an API.
我不确定我需要做什么?关闭CSRF当然可以,但我认为在创建这样的API时应该是我的错误。
Is there any other setup I need to do?
我需要做任何其他设置吗?
回答by max
Cross site request forgery (CSRF/XSRF) is when a malicious web page tricks users into performing a request that is not intended for example by using bookmarklets, iframes or just by creating a page which is visually similar enough to fool users.
跨站点请求伪造 (CSRF/XSRF) 是指恶意网页通过使用书签、iframe 或仅通过创建一个视觉上足够相似的页面来欺骗用户执行不打算执行的请求以欺骗用户。
The Rails CSRF protectionis made for "classical" web apps - it simply gives a degree of assurance that the request originated from your own web app. A CSRF token works like a secret that only your server knows - Rails generates a random token and stores it in the session. Your forms send the token via a hidden input and Rails verifies that any non GET request includes a token that matches what is stored in the session.
在Rails的CSRF保护作出了“经典” Web应用程序-它只是给出了一个程度的保证了请求源于自己的Web应用程序。CSRF 令牌就像一个只有你的服务器知道的秘密——Rails 生成一个随机令牌并将其存储在会话中。您的表单通过隐藏输入发送令牌,Rails 会验证任何非 GET 请求是否包含与会话中存储的内容相匹配的令牌。
However an API is usually by definition cross site and meant to be used in more than your web app, which means that the whole concept of CSRF does not quite apply.
然而,根据定义,API 通常是跨站点的,并且不仅仅用于您的 Web 应用程序,这意味着 CSRF 的整个概念并不完全适用。
Instead you should use a token based strategy of authenticating API requests with an API key and secret since you are verifying that the request comes from an approved API client - not from your own app.
相反,您应该使用基于令牌的策略,通过 API 密钥和密钥对 API 请求进行身份验证,因为您要验证请求来自已批准的 API 客户端 - 而不是来自您自己的应用程序。
You can deactivate CSRF as pointed out by @dcestari:
正如@dcestari 所指出的,您可以停用 CSRF:
class ApiController < ActionController::Base
protect_from_forgery with: :null_session
end
Updated.In Rails 5 you can generate API only applications by using the --apioption:
更新。在 Rails 5 中,您可以使用以下--api选项生成仅 API 的应用程序:
rails new appname --api
They do not include the CSRF middleware and many other components that are superflouus.
它们不包括 CSRF 中间件和许多其他多余的组件。
回答by Matt Waldron
Another way to turn off CSRF that won't render a null session is to add:
关闭不会呈现空会话的 CSRF 的另一种方法是添加:
skip_before_action :verify_authenticity_token
in your Rails Controller. This will ensure you still have access to session info.
在您的 Rails 控制器中。这将确保您仍然可以访问会话信息。
Again, make sure you only do this in API controllers or in other places where CSRF protection doesn't quite apply.
同样,请确保您只在 API 控制器或其他不完全适用 CSRF 保护的地方执行此操作。
回答by Mr. Tao
There is relevant info on a configuration of CSRF with respect to API controllers on api.rubyonrails.org:
关于api.rubyonrails.org上的 API 控制器的 CSRF 配置有相关信息:
?
It's important to remember that XML or JSON requests are also affected and if you're building an APIyou should change forgery protection method in
ApplicationController(by default::exception):class ApplicationController < ActionController::Base protect_from_forgery unless: -> { request.format.json? } endWe may want to disable CSRF protection for APIs since they are typically designed to be state-less. That is, the request APIclient will handle the session for you instead of Rails.
?
?
重要的是要记住 XML 或 JSON 请求也会受到影响,如果您正在构建API,您应该在
ApplicationController(默认情况下:)更改伪造保护方法:exception:class ApplicationController < ActionController::Base protect_from_forgery unless: -> { request.format.json? } end我们可能希望禁用 API 的 CSRF 保护,因为它们通常被设计为无状态的。也就是说,请求API客户端将为您而不是 Rails 处理会话。
?
回答by webaholik
回答by Ryosuke Hujisawa
If you want to exclude the sample controller's sample action
如果要排除示例控制器的示例操作
class TestController < ApplicationController
protect_from_forgery :except => [:sample]
def sample
render json: @hogehoge
end
end
You can to process requests from outside without any problems.
您可以毫无问题地处理来自外部的请求。
回答by Arish Khan
The simplest solution for the problem is do standard things in your controller or you can directely put it into ApplicationController
这个问题最简单的解决方案是在你的控制器中做标准的事情,或者你可以直接把它放到ApplicationController 中
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
end
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
end

