Я недавно наткнулся на статью, описывающую простейший грувлет, позволяющий исполнить любой код на Groovy у Вас на сервере. Мне это показалось очень удобным для организации отладочного бэкдора.
Проблема в то, что грувлеты — это всё таки сервер, а у нас есть еще толстый клиент на Swing. Для него мне хотелось бы сделать нечто похожее, но встраивание какого нибудь embedded Jetty или Tomcat только для этого в клиент выглядело как то слишком.
По счастью, мне попалась на глаза и другая статья — про наличие в стандартной библиотеке Java простейшего веб сервера. Вот им то я и решил воспользоваться.
Пишем Main:
public class Main {
public static void main(String[] args) {
// Порт может задаваться аргументом комадной строки, или как нибудь еще
HttpBackdoorRunner runner = new HttpBackdoorRunner(18999, true);
runner.start();
}
}
Продолжаем писать на груви, так легче :)
import com.sun.net.httpserver.HttpServer
import java.util.concurrent.Executors
/**
* Класс для запуска сервера с нашим хендлером (встроенный сервер - он не сервлет контейнер!)
*/
class HttpBackdoorRunner {
final int port
final boolean silent
HttpBackdoorRunner(int port, boolean silent) {
this.port = port
this.silent = silent
}
def start() {
try {
InetSocketAddress addr = new InetSocketAddress(port);
HttpServer server = HttpServer.create(addr, 0);
server.createContext("/", new BackdoorHandler());
server.setExecutor(Executors.newCachedThreadPool(
));
server.start();
}
catch(Exception e) {
if (silent) {
// Ignore
}
else throw new RuntimeException(e)
}
}
}
Теперь сам обработчик HTTP запросов:
/**
* Этот уровень абстракции мне нужен чтобы его же вызывать и из грувлета - для бэкдора на сервере
* В грувлете способ получения текста скипта, URI и стрима на вывод будут иные, а обработка скрипта - та же
*/
class BackdoorScriptRunner {
void runScript(script, responseBody, uri) {
def scriptOutput = new ByteArrayOutputStream()
if (script) {
// Redirect output
def saveOut = System.out
def stream = new PrintStream(scriptOutput)
System.out = stream
try{
def result = new GroovyShell().run(script, "dynamic.groovy");
}
catch (Throwable e) {
e.printStackTrace(stream);
}
System.out = saveOut
}
responseBody.println createHTML(uri, script, scriptOutput)
responseBody.close();
}
String createHTML(uri, script, scriptOutput) {
"""
<form action="${uri}" method="post">
<h2>BackDoor</h2>
Code comes here: <br>
<textarea cols="120" rows="5" name="groovyscript">
${script ? script : ""}</textarea>
<br>
<input type="submit" value="Go!" />
</form>
<br>
${scriptOutput.toString() ? "<h2>Output</h2><pre>${scriptOutput}</pre>" : ""}
"""
}
}
Запускаем, работает!
Автор: javax