我想将POST request
发送给我的本地开发者,如下所示:
HTTParty.post('http://localhost:3000/fetch_heroku',
:body => {:type => 'product'},)
但是,从服务器控制台报告
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
这是我的控制器和路线设置,非常简单。
def fetch_heroku
if params[:type] == 'product'
flash[:alert] = 'Fetch Product From Heroku'
Heroku.get_product
end
end
post 'fetch_heroku' => 'admin#fetch_heroku'
我不确定我需要做什么?关闭CSRF肯定会有用,但我认为在创建这样的API时应该是我的错误。
我还需要其他任何设置吗?
答案 0 :(得分:75)
跨站点请求伪造(CSRF / XSRF)是指恶意网页欺骗用户执行请求,例如通过使用bookmarklet,iframe或仅通过创建视觉上类似于欺骗用户的页面。
Rails CSRF protection是针对" classic"网络应用程序 - 它只是给出了一定程度的保证,即请求来自您自己的网络应用程序。 CSRF令牌就像只有您的服务器知道的秘密一样--Rails生成随机令牌并将其存储在会话中。您的表单通过隐藏的输入发送令牌,Rails验证任何非GET请求是否包含与会话中存储的令牌匹配的令牌。
然而,API通常是定义跨站点,并且意味着不仅仅用于您的Web应用程序,这意味着CSRF的整个概念并不完全适用。
相反,您应该使用基于令牌的策略来使用API密钥和密钥验证API请求,因为您要验证请求是来自经过批准的API客户端 - 而不是来自您自己的应用。
您可以按照@dcestari:
的指示停用CSRFclass ApiController < ActionController::Base
protect_from_forgery with: :null_session
end
已更新。在Rails 5中,您可以使用--api
选项生成仅限API的应用程序:
rails new appname --api
它们不包括CSRF中间件和许多其他超流程组件。
答案 1 :(得分:44)
关闭不会呈现空会话的CSRF的另一种方法是添加:
skip_before_action :verify_authenticity_token
在您的Rails控制器中。这将确保您仍然可以访问会话信息。
同样,请确保您只在API控制器或其他CSRF保护不太适用的地方执行此操作。
答案 2 :(得分:10)
有关api.rubyonrails.org上的API控制器的CSRF配置的相关信息:
⋮
记住XML或JSON请求也会受到影响非常重要,如果您要构建API,则应更改
:exception
中的伪造保护方法(默认情况下:{ {1}}):class ApplicationController < ActionController::Base protect_from_forgery unless: -> { request.format.json? } end
我们可能希望禁用API的CSRF保护,因为它们通常设计为无状态。也就是说,请求API客户端将为您处理会话而不是Rails。
⋮
答案 3 :(得分:5)
在Rails 5中,您还可以使用::API代替:: Base创建新类:
class ApiController < ActionController::API
end
答案 4 :(得分:0)
如果要排除样本控制器的样本操作
class TestController < ApplicationController
protect_from_forgery :except => [:sample]
def sample
render json: @hogehoge
end
end
您可以毫无问题地处理来自外部的请求。
答案 5 :(得分:0)
最简单的解决方案是在控制器中执行标准操作,也可以直接将其放入 ApplicationController
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
end
答案 6 :(得分:0)
如果您只想跳过一个或多个控制器动作(而不是整个控制器)的CSRF保护,请尝试
skip_before_action :verify_authenticity_token, only [:webhook, :index, :create]
[:webhook, :index, :create]
将跳过对这3个动作的检查,但是您可以更改为要跳过的任何内容
答案 7 :(得分:0)
如果您使用的是 Devise,请注意
<块引用>对于 Rails 5,protect_from_forgery
不再附加到 before_action
链,因此如果您在 authenticate_user
之前设置了 protect_from_forgery
,您的请求将导致“Can” t 验证 CSRF 令牌的真实性。”要解决此问题,请更改您调用它们的顺序,或使用 protect_from_forgery prepend: true
。