it-swarm.com.de

Wie lösche ich einen HTTP-Antwortheader?

Ich habe eine Situation, in der einer der Antwort-Header Content-Disposition entfernt werden muss. Also dachte ich daran, einen Servlet-Filter zu schreiben. Aber mir wurde klar, dass HttpServletResponse nur eine setHeader()-Methode hat, aber keine Methode, um sie zu entfernen . Wie kann ich das tun?

26
Daniel

Sie können nachträglich keine Header über die Standard-Servlet-API löschen. Ihre beste Wette ist, zu verhindern, dass der Header gesetzt wird. Sie können dies tun, indem Sie eine Filter erstellen, die die ServletResponse durch eine benutzerdefinierte HttpServletResponseWrapper -Implementierung ersetzt, die den Job von setHeader() überspringt, wenn der Headername Content-Disposition ist.

Grundsätzlich gilt:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
        public void setHeader(String name, String value) {
            if (!name.equalsIgnoreCase("Content-Disposition")) {
                super.setHeader(name, value);
            }
        }
    });
}

Ordnen Sie diesen Filter einfach dem gewünschten URL-Muster zu, damit er ausgeführt werden kann.

40
BalusC

Dies ist möglicherweise nicht mit der Servlet-API kompatibel, aber das Festlegen des Werts auf null funktioniert auf GlassFish 4 und wahrscheinlich auch auf Tomcat, da dies unter GlassFish liegt. 

Wir müssen die Servlet-API-Spezifikation wirklich aktualisieren, um entweder eine Methode hinzuzufügen, die das Entfernen von Headern zulässt, oder um die Verwendung von setHeader mit einem Nullwert offiziell zu unterstützen. 

Dies ist beispielsweise wichtig, wenn Sie für Ihre Webanwendung eine Sicherheitsbedingung (SSL/TLS) verwenden. Das Zwischenspeichern von statischen Ressourcen wird jedoch dadurch erschwert, dass der Container automatisch Header hinzufügt, um das Zwischenspeichern zu verhindern (Sie können versuchen, sie mit disableProxyCaching und zu deaktivieren securePagesWithPragma auf Tomcat/GlassFish). Ich habe bereits einen Servlet-Filter für die Cache-Steuerung, der für nicht sichere Inhalte hervorragend geeignet ist. Daher möchte ich die Cache-Steuerung alle an einem Ort aufbewahren und Prama und Cache-Control einfach auf Null setzen, um alle mit dem Container hinzugefügten Header zu löschen.

3
Ryan

Mit Spring 4 funktioniert das nicht. Ich versuche, den Expires-Antwortheader zu entfernen. Für jede Seite. So wie:

public class CachingFilter implements Filter {
    private final Log logger = LogFactory.getLog(getClass());

    public CachingFilter() {}
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        logger.debug("doFilter()");
        chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
            public void setHeader(String name, String value) {
                logger.debug("setHeader(" + name + ","+value+")");

                if (!name.equalsIgnoreCase("Expires")) {
                    super.setHeader(name, value);
                }
            }
        });
    }

    public void init(FilterConfig fConfig) throws ServletException {}
}

Und so füge ich den Filter hinzu:

public class AppConfig implements WebApplicationInitializer {
    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
    private static final String DISPATCHER_SERVLET_MAPPING = "/";

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(AppContext.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);

        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);

        FilterRegistration.Dynamic noCache = servletContext.addFilter("noCacheFilter", new CachingFilter());
        noCache.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

setHeader () wird für Expires und Cache-Control aufgerufen, aber ich kann den Filterwert Expires oder den Cache-Control-Wert nicht überschreiben. Ich kann den Cache-Control-Wert hinzufügen. Es wird zu einem Array von Werten, wenn ich setHeader in Cache-Control aufrufe. Aber ich muss den Header löschen.

1
yetimoner

Wie die anderen Antworten. Es gibt keine Möglichkeit, einen Header nach dem Setzen zu entfernen, zumindest nicht als Standard (glassfish lässt den Header auf null zurücksetzen). Am Ende des Tages hätten Sie also zwei Möglichkeiten:

  1. antwort zurücksetzen.

    response.reset ()

Dies entfernt effektiv ALLE Header und auch alle Daten, die je nach Fall eine gute Alternative darstellen können (in meinem Fall nach Authentifizierungsfehlern). Wenn die Antwort bereits festgeschrieben ist, erhalten Sie eine IllegalStateException. 

  1. Setzen Sie den Header auf leere Zeichenfolge. Die Header werden dadurch natürlich nicht entfernt. Die http-Spezifikation enthält jedoch nur einige Definitionen für und einen leeren Wert in den Überschriften Accept-Encoding, TE (Transfer Encoding) und Host. In Abhängigkeit von Ihren Anforderungen können Sie dies in Ihrer Anwendungsebene steuern.
0
le0diaz