2009-10-02 49 views
4

我正在创建一个API服务,该服务允许人们向API调用提供图像的URL,并且该服务下载要处理的图像。如何限制Net :: HTTP请求的大小?

如何确保有人不给我像5MB图像的URL?有没有办法限制请求?

这是我到目前为止,基本上抓住了一切。

req = Net::HTTP::Get.new(url.path) 
    res = Net::HTTP.start(url.host, url.port) { |http| 
    http.request(req) 
    } 

感谢, 康拉德

回答

2

尝试运行这个第一:

Net::HTTP.start(url.host, url.port) { |http| 
    response = http.request_head(url.path) 
    raise "File too big." if response['content-length'].to_i > 5*1024*1024 
} 

你仍然有竞争条件(你做HEAD请求后,有人可能会掉出文件),但在这是一个简单的例子,它向服务器询问将从GET请求发回的标头。

+0

酷,非常感谢你!这有帮助! – chuboy 2009-10-02 21:46:44

+1

这不适用于HTTP/1.1分块编码或HTTO/1.0连接:关闭且无内容长度。 – panzi 2013-09-11 15:43:15

6

cwninja不幸的是你给出的答案只适用于意外攻击。一个聪明的攻击者将毫不费力地击败那张支票。他的方法不应该被使用有两个主要原因。首先,没有什么能保证HEAD响应中的信息将匹配相应的GET响应。一个正常行为的服务器肯定会这样做,但恶意的演员不必遵循规范。攻击者可以简单地发送一个HEAD响应,说明它的Content-Length小于阈值,但在GET响应中提供一个巨大的文件。但是,这甚至不包括服务器使用Transfer-Encoding:chunked头集发回响应的可能性。分块的响应可能永远不会结束。有些人将您的服务器指向永不停止的响应,即使您的HTTP客户端强制执行超时,也可能会执行一项微不足道的资源耗尽攻击。

要正确执行此操作,您需要使用HTTP库,以便在收到字节时对它们进行计数,如果超出阈值则会中止。我可能会推荐Curb而不是Net :: HTTP。 (你甚至可以用Net :: HTTP做这件事)如果你使用on_body和/或on_progress回调函数,你可以计算传入的字节数,并在收到一个太大的文件时中止响应。显然,正如cwninja已经指出的那样,如果您收到的Content-Length头部大于您的阈值,您也想中止。路边也是notably faster than Net::HTTP

+0

DOS的最简单的方法是简单地输入一个非常缓慢的响应页面的URL(或回到网站本身,导致DOS的反馈循环)?超时应该照顾到这一点(尽可能地),同样的逻辑可以用于这个问题和大型响应大小问题的DOS元素。 HEAD请求提供验证,而不是保护。 – cwninja 2009-10-11 17:42:25

+0

回到网站本身的请求通常会失败,除非它是一个完全异步的环境,不会阻塞。但是这很容易检查:不要允许请求到你自己的主机名。 – 2009-10-11 17:52:25

+0

黑名单几乎总是会导致失败。那么http:// someproxyservice /?q = http://yoursite.com? – cwninja 2009-10-11 17:58:16

1

另一种方式来限制下载大小(完整的代码应检查响应状态,异常处理等,这只是一个例子)

Net::HTTP.start(uri.host, uri.port) do |http| 
    request = Net::HTTP::Get.new uri.request_uri 
    http.request request do |response| 
# check response codes here 
     body='' 
     response.read_body do |chunk| 
      body += chunk 
      break if body.size > MY_SAFE_SIZE_LIMIT 
     end 
     break 
    end 
end