[英]How to limit 10 requests per second for 3 urls(including all 3) from Spring application
[英]How to Limit web requests per second to avoid spamming and denial of service
我有一个网页,该网页接受用户的搜索查询并在数据库中进行搜索。 由于此查询非常耗时,即使有适当的索引,我也希望将搜索请求限制为每位用户每2秒1次。 目前我正在使用以下方法(草图)
限制:
1)我的网站上没有登录系统。 相反,我依赖于请求标头来获取用户的IP地址和用户ID。
ALGO:
1) Maintain a map of ips and user ids and their latest search timestamp.
2) For every search request,
2.1) If user has searched in last two seconds: Show error message
2.2) Else, allow him to search
我想知道这种方法是否足够? 由于IP地址和用户ID均来自请求标头,因此垃圾邮件发送者是否可以更改请求标头?
这是一个简单的servlet过滤器,可防止用户在一段时间内访问资源(可能需要改进):
// (requires http sessions enabled)
public class AccessControlFilter implements Filter {
private final String ACCESS_CONTROL_SESSION_KEY = String.valueOf("NextAccessAllowedTime".hashCode());
// how long to prevent users from accessing in ms?
private final long penaltyTime = 1000 * 2;
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// is http request?
if (req instanceof HttpServletRequest) {
HttpSession session = ((HttpServletRequest) req).getSession();
// has access value in session?
Object value = session.getAttribute(ACCESS_CONTROL_SESSION_KEY);
if (value != null) {
Date nextAccessAllowed = new Date(((long) value));
if (new Date().before(nextAccessAllowed)) {
// handle access denied (better redirect to another url or display message then sending this response code?)
((HttpServletResponse) res).sendError(HttpServletResponse.SC_FORBIDDEN, "Access to this resource is denied until: " + nextAccessAllowed);
res.flushBuffer();
return;
}
}
session.setAttribute(ACCESS_CONTROL_SESSION_KEY, System.currentTimeMillis() + penaltyTime);
}
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("Starting " + this.getClass().getSimpleName() + " on resource: \"" + config.getServletContext().getFilterRegistration(config.getFilterName()).getUrlPatternMappings().iterator().next() + "\" with penalty time: "
+ penaltyTime + "ms!");
}
@Override
public void destroy() {
System.out.println("Stopping " + this.getClass().getSimpleName());
}
}
像这样在web.xml中启用它:
<filter>
<filter-name>acf</filter-name>
<filter-class>your.package.AccessControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>acf</filter-name>
<!-- Resource to check. Should be the url your search form posts to! -->
<url-pattern>/search/*</url-pattern>
</filter-mapping>
如果您正在http服务器级别上寻找模块,请查看“ mod evasive”。
也许您应该尝试缓存搜索结果(即ehcache)并创建一个固定的线程池来处理搜索,因此您可以一次控制搜索量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.