Я пытаюсь систематически реагировать на разделение ответа HTTP. Я разработал класс обертки для HttpServletResponse под названием HardenedHttpServletResponse, который смягчает попытки расщепления.Как мне заставить Джерси вызвать метод ресурса с помощью оболочки HttpServletResponse?
К сожалению, я не могу заставить Джерси позвонить по моему методу ресурса с моим HardenedHttpServletResponse. Я получаю null s при попытке.
Вот изобретенный ресурс JAX-RS с расщеплением уязвимостью ответа HTTP, который является годным для использования, помещая проценты в кодировке CRLFs (%0d%0a
) в имени файл параметре запроса:
AttachmentResource.java:
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
@Path("/attachment")
@Produces(MediaType.APPLICATION_JSON)
public final class AttachmentResource {
@GET
@Path("/file")
public StreamingOutput getAttachment(
@Context HttpServletResponse response,
@QueryParam("filename") String filename
) throws Exception {
response.setHeader(
"content-disposition",
"attachment; filename=" + filename
);
return new DummyStreamingOutput();
}
}
Вот фиктивная реализация StreamingOutput, чтобы сделать его несколько полный пример:
DummyStreamingOutput.java:
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
private static DummyFileStreamingOutput implements StreamingOutput {
@Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
String message = "Hello, World!";
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
}
}
Вот HttpServletResponse класс-оболочка, которая уменьшает расщепление ответа HTTP, бросая исключение, если он обнаруживает, CR или LF символы в именах заголовков или значений:
HardenedHttpServletResponse.java:
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.ws.rs.core.Context;
final class HardenedHttpServletResponse extends HttpServletResponseWrapper {
@Inject
HardenedHttpServletResponse(@Context HttpServletResponse response) {
super(response);
}
@Override
public void setHeader(String name, String value) {
mitigateResponseSplitting(name);
mitigateResponseSplitting(value);
super.setHeader(name, value);
}
@Override
public void addHeader(String name, String value) {
mitigateResponseSplitting(name);
mitigateResponseSplitting(value);
super.setHeader(name, value);
}
@Override
public void setIntHeader(String name, int value) {
mitigateResponseSplitting(name);
super.setIntHeader(name, value);
}
@Override
public void setDateHeader(String name, long date) {
mitigateResponseSplitting(name);
super.setDateHeader(name, date);
}
private void mitigateResponseSplitting(String value) {
if (value != null && (value.contains("\r") || value.contains("\n"))) {
throw new HttpResponseSplittingException();
}
}
}
Джерси поставляет фактический объект ответа, если ответ параметр имеет тип @Context HttpServletResponse, но нуль если ответ параметр имеет тип @Context HardenedHttpServletResponse.
Как получить Джерси, чтобы вызвать метод ресурса с помощью обертки HttpServletResponse?
Хороший ответ. Спасибо. Я должен был изменить его, чтобы быть **. Proxy (false) ** код для адаптации. Он работает, и я узнал намного больше о HK2 в специфическом и Джерси-ДЭ в целом, из которого я могу применить в будущей работе. –
Извините, я забыл, что он принимает аргумент. Это должно быть 'proxy (true)'. По умолчанию это неверно, поэтому, если вы не хотите прокси-сервера, вы можете просто оставить первые два прикованных вызова. Причина, по которой вам нужно прокси-серверу, - это если вам нужно вставить ее в одноэлементный, то она будет обернута в локальный прокси-сервер потока. Но если он вводится в объект с областью запроса (не singleton), тогда он не будет прокси (реальным объектом) из-за второго прикованного вызова. Это также то, как он настроен для HttpServletRequest. Вот почему вы можете вводить его в одиночный ContainerRequestFilter –