防火墙根据规则(或策略)阻止请求。
示例:如果一个 IP 每秒发送超过 10 个请求,则将所有后续请求阻止 2 小时。
我可以使用 Spring MVC 做到这一点吗?
好吧,你可以用它编程任何东西:是的,你可以。(尽管您只能发送一个空响应,而不是像防火墙那样阻止连接。)您所要做的就是考虑规则并实施它们。
但这并不像设置防火墙那么简单,而且很可能这不是您的应用程序要做的工作。
对于上面的示例,您可以创建一个HashMap
存储从控制器请求任何内容的每个 IP;和一个柜台。如果该计数器大于 10,您会将 IP 移动到另一个HashMap
(例如blockedIpsMap
)两个小时。blockedIpsMap
然后,向控制器发出的每个请求都应在发送响应之前检查 IP 是否不在其中。
再次:可能吗?是的。你应该这样做吗?仅当您确实需要这样做(例如,如果您受到很多攻击)并且无法使用防火墙(旨在执行此操作的软件)进行管理时。
示例代码:
构建应用程序服务器(和 Servlet)的方式必须始终返回响应。我的意思是:你不能不发送回复。(Servlet 和应用程序服务器被构建为健壮的,不发送响应在他们看来是失败的。)
正如我所说,防火墙可以阻止连接,并且永远不会在需要时发送响应。
无论如何,既然你必须发送一个响应,你所能做的就是发送一个空的。
使用Spring MVC,发送一个空响应就是它看起来的样子:
@RequestMapping(value = "/path")
@ResponseBody
public String emptyResponse() {
if (shouldIblock()) {
return "";
}
else {
// do the stuff as usual
}
}
上面的代码将返回内容长度 = 0 的 HTTP 200-OK 响应。
不过,您最好的选择是使用Servlet 过滤器“介于”每个请求和每个控制器之间。
这是一个帮助您入门的代码(不言自明):
package ipfilter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class BlockIPFilter implements Filter {
public void init(FilterConfig config) throws ServletException { }
public void destroy() { }
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) throws IOException, ServletException {
String userip = request.getRemoteAddr();
if (isIpAllowed(userip)) {
filterchain.doFilter(request, response); // go on
} else {
HttpServletResponse httpResponse = null;
if (response instanceof HttpServletResponse) {
httpResponse = (HttpServletResponse) response;
}
// will return a 403-Forbidden error
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Error message (may wanna leave empty)");
/* or you can just comment the line above and an empty
* response 200-OK will be sent, giving no clue to the user that he was blocked
*/
}
}
public boolean isIpAllowed(String ip) {
// maybe add to the HashMap and do any other checking
return false;
}
}
还要将此添加到您的顶部web.xml
:
<filter>
<filter-name>BlockIPFilter</filter-name>
<filter-class>ipfilter.BlockIPFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BlockIPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>