使用POST args

时间:2018-03-23 11:20:43

标签: nginx

我需要根据2个条件在nginx中应用速率限制:

  1. 方法是POST
  2. post args包括" _api"键
  3. 1。这无法检测发布请求中的_api密钥:

    limit_req_zone "$arg__api" zone=api_zone:10m rate=30r/m;
    limit_req zone=api_zone burst=10 nodelay;
    

    2。这可以检测POST方法:

    map $request_method $limit {
      default "";
      POST $binary_remote_addr;
    }
    
    limit_req_zone $limit zone=my_zone:10m rate=20r/m;
    limit_req zone=my_zone burst=10 nodelay;
    

    那么我怎样才能检测到它是POST并且帖子包含_api键?

    更新1

    我只是尝试用post检测post中的_api键,但它也不起作用:

    map $request_body $api { 
      "_api" $binary_remote_addr;
      default "";
    } 
    limit_req_zone $api zone=api_api:10m rate=30r/m;
    limit_req zone=api_api burst=10 nodelay;
    

1 个答案:

答案 0 :(得分:1)

好的,经过数小时的研究和大量的反复试验,我确定了:

$ args 仅包含GET数据

$ request_body 包含POST数据,但仅在使用时才可用:

proxy_pass
fastcgi_pass
uwsgi_pass
scgi_pass

$ request_body 是一个字符串,当可用时未解析为JSON,因此您无法使用$ args执行$ request_body_api。

我无法通过在地图中直接使用$ request_body来实现此功能:

map $request_body $body {
  default "";
  "~*.*(_api)" $binary_remote_addr;
}
limit_req_zone $body zone=body:10m rate=30r/m;
limit_req zone=body burst=5 nodelay;

我能找到让这个工作的唯一方法就是在包含帖子的标题中添加一个cookie,这样可行,但效率不高,好像帖子请求很大,会消耗很多不必要的资源。

add_header Set-Cookie post_data=$request_body;
map $http_cookie $cook_ {
  default "";
  "~*post_data=.*(\"_api\")" $binary_remote_addr;
}

limit_req_zone $cook zone=cook:10m rate=30r/m;
limit_req zone=cook burst=5 nodelay;

如果我做了任何不正确的陈述/妄想,或者如果有人知道更好的方法,那么请告诉我,这有效,但有点像黑客!