我在使用 Web 服务时遇到问题,用户试图通过循环随机 ID 来猜测应用程序 ID。
错误请求来自随机 IP,所以我不能只禁止他们的 IP(除非我动态地这样做,但我还没有调查)。
目前,当我检测到一个客户端尝试了 10 次错误的应用 ID 尝试时,我会将它们放在我的应用中的阻止列表中,并在当天拒绝来自该 IP 的进一步请求。
我想尽量减少我的服务器需要做的工作量,因为坏客户端即使被拒绝也会继续发送 1000 多个请求。我知道有动态防火墙解决方案,但现在想要在我的应用程序中轻松实现。目前我正在 sleep 5 秒钟以减少调用,但我想做的只是不向客户端发送响应,所以它必须超时。
有人知道如何在 Java 中,在 JAX-RS 中做到这一点吗?
我的服务是这样的,
@Path("/api")
public class MyServer {
@GET
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
@Path("/my-request")
public String myRequest(String type,
@Context HttpServletRequest requestContext,
@Context HttpServletResponse response) {
...
}
最佳答案
您正在寻找 asynchronous responses JAX-RS 支持。 tutorial for Jersey包含一些如何实现对请求的异步响应的示例。
对于异步响应,负责响应请求的线程在请求完成之前就已经被释放以处理另一个请求。通过添加带有 @Suspended
注释的参数来激活此功能。您还需要做的是注册一个专用的 scheduler它负责在给定超时后唤醒您的请求,如下例所示:
@Path("/api")
public class MyServer {
private ScheduledExecutorService scheduler = ...;
@GET
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
@Path("/my-request")
public String myRequest(String type,
@Context HttpServletRequest requestContext,
@Context HttpServletResponse response,
@Suspended AsyncResponse asyncResponse) {
scheduler.schedule(new Runnable() {
@Override
public void run() {
asyncResponse.resume(...)
}
}, 5, TimeUnit.SECOND);
}
}
这样,在 5 秒的等待时间内没有线程被阻塞,这为同时处理其他请求提供了机会。
JAX-RS 不提供在没有答案的情况下完全丢弃请求的方法。您需要保持连接打开以产生超时,如果您终止连接,则会通知用户终止。你能做的最好的就是永远不要回答异步请求,但这仍然会消耗一些资源。如果您想避免这种情况,则必须在 JAX-RS 之外解决问题,例如通过另一台服务器代理请求。
一种方法是set up mod_proxy您可以在其中使用恶意请求的错误代码回答代理,并为此类请求设置非常大的重试限制。
关于java - 如何让客户端等待 Java JAX-RS 服务以防止 DOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32874305/