我正在创建一个接收HTTP请求的Java应用程序。对于每个进来的请求,我启动一个新线程,在该线程中我正在读取请求并执行必要的操作。但是,我想阻止用户执行“慢速Loris攻击”,因此我在考虑为线程提供maxTime
值。如果线程花费的时间超过maxTime
,它将终止,无论如何。因此它也会阻止慢速连接,这是不问题。
但是,我不知道这样做的正确方法是什么。我尝试了下面的代码,但这段代码阻止了我的主线程。我正在寻找一种方法来做类似这样的事情,而不会阻塞主线程。
代码:
/**
* Executor which is used for threadpools.
*/
private ExecutorService executor;
/**
* Constructor for the class RequestReceiver.
* Initializes fields.
*/
public RequestReceiver() {
this.executor = Executors.newFixedThreadPool(200);
}
@Override
public void run() {
try {
this.serverSocket = new ServerSocket(port);
} catch (IOException ex) {
Logger.getInstance().logText("Could not start server on port: " + port);
return;
}
Logger.getInstance().logText("Server running at port: " + port);
try {
while (shouldContinue) {
Socket client = serverSocket.accept();
HTTPRequestHandler handler = new HTTPRequestHandler(client);
Thread t = new Thread(handler);
executor.submit(t).get(10, TimeUnit.SECONDS); //This line is blocking
}
} catch (IOException ex) {
Logger.getInstance().logText("Server is shutdown");
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
Logger.getInstance().logText("Thread took too long, it's shutdown");
}
}
答案 0 :(得分:1)
对您的示例进行的最少更改可以为您提供类似于您想要的内容,即提交新任务。
Socket client = serverSocket.accept();
HTTPRequestHandler handler = new HTTPRequestHandler(client);
Future f = executor.submit(handler);
executor.submit(()->{
try{
f.get(10, TimeUnit.SECONDS);
} catch(TimeoutException to){
//timeout happened, this will cancel/interrupt the task.
f.cancel(true);
} catch(Exception e){
throw new RuntimeException(e);
//something else went wrong...
}
});
这可以工作,但它会阻止一个额外的线程等待get调用。您还需要在HTTPRequestHandler代码中处理中断。
另一种方法是使用ScheduledExecutorService
。
答案 1 :(得分:0)
您的方法存在一些问题:
我正在创建一个接收HTTP请求的Java应用程序。对于每个进来的请求,我启动一个新线程,在该线程中我正在读取请求并执行必要的操作。
这是耗尽内存或其他资源的可靠方法。相反,在servlet容器(tomcat,jetty)中运行应用程序,让它为您处理多线程。只需确保处理请求的代码是“线程安全的”,因为它将由多个线程同时调用。
如果您必须使用ServerSocket,请使用具有固定线程数的ExecutorService。 (绝不使用无限数量的线程)
但是,我想阻止用户执行“慢速Loris攻击”
要防止slowloris攻击,您应该在http服务器(例如Apache)后面运行您的应用程序,并确保安装相应的安全模块。例如:http://www.techrepublic.com/blog/smb-technologist/secure-your-apache-server-from-ddos-slowloris-and-dns-injection-attacks/
我在考虑为线程提供maxTime值。如果线程花费的时间超过maxTime,它将终止,无论如何。
这不是一个好主意。通常,当您收到HTTP请求时,控制器(处理请求的代码)必须尽快回复,但执行此操作的方法是优化请求的处理(例如,不要执行操作在处理http请求时花费太长时间)。 如果您的处理时间很快,但从客户端的角度来看,服务器没有响应,那么您应该考虑分发您的应用程序(将许多服务器实例置于负载均衡器之后)