2016-11-10 2 views
1

Я пытаюсь систематически реагировать на разделение ответа 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?

ответ

1

Вы можете просто сделать инъекцию, добавив систему DI.

resourceConfig.register(new AbstractBinder() { 
    @Override 
    public void configure() { 
     bindAsContract(HardenedHttpServletResponse.class) 
      .proxy(false) 
      .proxyForSameScope(false) 
      .in(RequestScoped.class); 
    } 
}); 

Вам нужно будет сделать класс public, а также его конструктор общественности, так что система DI может создать. Это позволит придать HardenedHttpServletResponse

Смотрите также:

+0

Хороший ответ. Спасибо. Я должен был изменить его, чтобы быть **. Proxy (false) ** код для адаптации. Он работает, и я узнал намного больше о HK2 в специфическом и Джерси-ДЭ в целом, из которого я могу применить в будущей работе. –

+0

Извините, я забыл, что он принимает аргумент. Это должно быть 'proxy (true)'. По умолчанию это неверно, поэтому, если вы не хотите прокси-сервера, вы можете просто оставить первые два прикованных вызова. Причина, по которой вам нужно прокси-серверу, - это если вам нужно вставить ее в одноэлементный, то она будет обернута в локальный прокси-сервер потока. Но если он вводится в объект с областью запроса (не singleton), тогда он не будет прокси (реальным объектом) из-за второго прикованного вызова. Это также то, как он настроен для HttpServletRequest. Вот почему вы можете вводить его в одиночный ContainerRequestFilter –

Смежные вопросы