Jersey ContainerResponseFilter未应用于所有回复

时间:2016-09-19 07:40:33

标签: filter jersey jetty servlet-filters dropwizard

我有一个Dropwizard 1.0.0应用程序,使用ContainerResponseFilter我希望看到一系列标头应用于每个资源 - 但我只看到它们应用于根级文档。

过滤类:

package com.uk.jacob.filters;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;

public class SecurityFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
        MultivaluedMap<String, Object> headers = containerResponseContext.getHeaders();

        headers.add("strict-transport-security", "max-age=31536000");
        headers.add("x-content-type-options", "nosniff");
        headers.add("x-frame-options", "SAMEORIGIN");
        headers.add("x-xss-protection", "1;  mode=block");
    }
}

申请类:

package com.uk.jacob;

import com.uk.jacob.filters.SecurityFilter;
import com.uk.jacob.resources.HomepageResource;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.client.HttpClientBuilder;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.dropwizard.views.ViewBundle;
import org.apache.http.client.HttpClient;

public class websiteApplication extends Application<websiteConfiguration> {

    public static void main(final String[] args) throws Exception {
        new websiteApplication().run(args);
    }

    @Override
    public String getName() {
        return "website";
    }

    @Override
    public void initialize(final Bootstrap<websiteConfiguration> bootstrap) {
        bootstrap.addBundle(new ViewBundle<websiteConfiguration>());
        bootstrap.addBundle(new AssetsBundle("/public/", "/public"));
    }

    @Override
    public void run(final websiteConfiguration configuration, final Environment environment) {
        final HttpClient httpClient = new HttpClientBuilder(environment).using(configuration.getHttpClientConfiguration()).build(getName());

        environment.jersey().register(new SecurityFilter());
        environment.jersey().register(new HomepageResource(httpClient));
    }

}

1 个答案:

答案 0 :(得分:0)

您的问题是AssetBundle。 AssetBundles是独立的servlet,它们不通过泽西生态系统。来自消息来源:

@Override
public void run(Environment environment) {
    LOGGER.info("Registering AssetBundle with name: {} for path {}", assetsName, uriPath + '*');
    environment.servlets().addServlet(assetsName, createServlet()).addMapping(uriPath + '*');
}

这就是为什么不在资产资源上调用过滤器的原因。解决方法是编写一个额外的ServletFilter(旧样式)来过滤资产请求并在那里添加标题。

为了还将标题添加到资产包中,您必须使用普通的servlet过滤器并将其注册到DW:

以下是我的ServletFilter的代码:

public class ServletRequestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Asset filter");

        HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
        httpServletResponse.addHeader("ARTUR", "test");

        chain.doFilter(request, httpServletResponse);
    }

    @Override
    public void destroy() {
    }

}

然后注册如下:

public class ViewApplication extends io.dropwizard.Application<Configuration>{

    @Override
    public void run(Configuration configuration, Environment environment) throws Exception {
        environment.jersey().register(ViewResource.class);
        environment.jersey().register(HeaderResponseFilter.class);
        environment.servlets().addFilter("Custom-Filter-Name", new ServletRequestFilter()).addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/assets/*");
    }

    @Override
    public void initialize(Bootstrap<Configuration> bootstrap) {
        super.initialize(bootstrap);
        bootstrap.addBundle(new ViewBundle<>());
        bootstrap.addBundle(new AssetsBundle("/assets/", "/assets"));
    }

    public static void main(String[] args) throws Exception {
        new ViewApplication().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
    }

}

注意:我正在为/assets/中的网址注册资产包。在我的过滤器注册中也会注意到这一点(仅过滤资源资源)。或者,您可以在所有通话中匹配它并通过它过滤所有内容(这样您可以摆脱我认为的球衣对应物)。

最后测试我的资源:

artur@pandaadb:~/dev/repo/sandbox$ curl -v "http://localhost:9085/assets/test.txt"
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /assets/test.txt HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Mon, 19 Sep 2016 15:07:13 GMT
< ARTUR: test
< Last-Modified: Mon, 19 Sep 2016 14:52:37 GMT
< ETag: "0d1ae97d61a8900c99abddb8741febaf"
< Content-Type: text/plain;charset=utf-8
< Vary: Accept-Encoding
< Content-Length: 11
< 
asd
asd
* Connection #0 to host localhost left intact

请注意我的自定义标题ARTUR: test

此致

artur