New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security-related HTTP headers not written if response is committed during INCLUDE dispatch and RequestDispatcher is not obtained via HttpServletRequest object #6414
Comments
Thanks for the report, @mjagus! Would you be able to post a simple example that reproduces the issue? |
@mjagus Awesome, thanks. I'll do a bit more digging, but a brief look at the Servlet Spec doesn't point to a straight-forward way to intercept |
@mjagus Looking at the SiteMesh code, I see that it uses the servlet context for forwards. Does SiteMesh use it for includes as well somewhere? |
@jzheaux It does use includes as well. For example here: https://github.com/sitemesh/sitemesh2/blob/master/src/java/com/opensymphony/sitemesh/compatability/OldDecorator2NewDecorator.java As for suggestions, at first I thought that |
So, treating The code could possibly expose a boolean like How well would something like this work for your usecase: List<HeaderWriter> earlyWriters = ...;
HeaderWriterFilter earlyFilter = new HeaderWriterFilter(earlyWriters);
earlyFilter.setWriteHeadersEagerly(true);
http
.addFilterBefore(earlyFilter, HeaderWriterFilter.class)
// .headers() added by default Where Or, another application of that might be: http
.addObjectPostProcessor(new ObjectPostProcessor<HeaderWriterFilter>() {
public HeaderWriterFilter postProcess(HeaderWriterFilter filter) {
filter.setWriteHeadersEagerly(true);
return filter;
}
} Again with the understanding that this would mean cache control is written early. Agreed that we can only take the wrapping approach so far, especially since servlet context isn't request-scoped, making it impossible to manage inside a filter chain. You could potentially wrap it yourself and subclass |
Hi @jzheaux ! Making such thing configurable seems like a great idea, but I think it would be way better to configure it on a I imagine example Java Config would look something like this (assuming deferred approach would be the default one in order to maintain backward compatibility):
and similar XML config:
I see that PR is already made but maybe there's still some time for discussion? Please tell me what you think. As for potential workarounds, we are currently instrumenting SiteMesh clasess using AspectJ to redirect include calls to |
Summary
In #5499 a bug was fixed which caused security-related headers to not appear in HTTP response if that response was commited during INCLUDE dispatch. The solution was to wrap both
HttpServletRequest
andRequestDispatcher
object in order to interceptRequestDispatcher::include
call. That fix doesn't work if RequestDispatcher is obtained via some other means thanHttpServletRequest::getRequestDispatcher
method.In my particular case it's the SiteMesh 2.x servlet filter that obtains dispatcher via
ServletContext::getRequestDispatcher
and then callsinclude
method on it. The returned dispatcher is unfortunately not a wrapper created byHeaderWriterFilter
which means that no security headers are added to HTTP response.Actual Behavior
Assuming that security-related headers are enabled in spring-security:
HeaderWriterFilter
is invoked and both request and response objects are wrapped.RequestDispatcher::include
on dispatcher obtained via some other means thanHttpServletRequest::getRequestDispatcher
method.This results in security-related headers not being added to HTTP response.
Expected Behavior
The way of obtaining
RequestDispatcher
object should not be a factor when adding security-related headers to response.Configuration
Tomcat 8.5.34
SiteMesh 2.4.2
Spring-based web application which uses JSPs and decorates them using SiteMesh.
Version
5.1.2
Sample
spring-security-gh6414.zip
Attached is a Zip file containing a simple Spring Boot application. Simply run the de.chschu.spring.security.gh6414.Application main class.
The response of http://localhost:8080/positive will have the headers, while http://localhost:8080/negative (which simply includes the other one) will not.
The text was updated successfully, but these errors were encountered: