Skip to content

Duplicate cache headers #4199

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

Closed
apixandru opened this issue Feb 3, 2017 · 1 comment
Closed

Duplicate cache headers #4199

apixandru opened this issue Feb 3, 2017 · 1 comment
Labels
in: web An issue in web modules (web, webmvc) type: bug A general bug
Milestone

Comments

@apixandru
Copy link

This issue was originally reported here spring-projects/spring-boot#8188

Updating the latest spring boot also updates the spring security from 4.1.x to 4.2.x

The previous version of spring security didn't write the cache control header if it was already set, now it always sets it, effectively ignoring the explicitly set settings.

Before, the writeHeader method used to write

public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
	if (hasHeader(response, CACHE_CONTROL) || hasHeader(response, EXPIRES)
			|| hasHeader(response, PRAGMA)) {
		return;
	}
	this.delegate.writeHeaders(request, response);
}

Now, it's simply

public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
	for (Header header : headers) {
		for (String value : header.getValues()) {
			response.addHeader(header.getName(), value);
		}
	}
}

This is the commit 57d7ad0

sample project here
https://github.com/apixandru/case-study/tree/master/spring-boot-duplicate-headers

it turns out that WebSecurityConfigurerAdapter enables the cache control headers that you were missing

happens with a weblogic deployment


$ curl --head -i http://192.168.0.248:7001/test/b.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0HTTP/1.1 200 OK
Cache-Control: public
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Date: Fri, 03 Feb 2017 20:20:36 GMT
Pragma: cache
Pragma: no-cache
Transfer-Encoding: chunked
Accept-Ranges: bytes
Content-Type: text/plain
Expires: 0
Last-Modified: Fri, 03 Feb 2017 20:20:11 GMT
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
@rwinch rwinch added this to the 4.2.2 milestone Feb 3, 2017
@rwinch rwinch added the type: bug A general bug label Feb 3, 2017
@apixandru
Copy link
Author

The reason why this works with the embedded tomcat is that the filter chain is built differently.
With weblogic, the filter is added first, with the embedded tomcat it's down the line.

weblogic spring boot 1.5.1
security cache control headers written in the DelegatingFilterProxyRegistrationBean, which is second in the chain

filterChain = {FilterChainImpl@19626} 
 filters = {LinkedList@19746}  size = 8
  0 = {NoCacheFilter@19625} 
  1 = {DelegatingFilterProxyRegistrationBean$1@19678} <- cache control headers written here
  2 = {OrderedRequestContextFilter@19755} 
  3 = {OrderedHttpPutFormContentFilter@19756} 
  4 = {OrderedHiddenHttpMethodFilter@19757} 
  5 = {OrderedCharacterEncodingFilter@19758} 
  6 = {ErrorPageFilter@19759} 
  7 = {TailFilter@19760} 

embedded tomcat spring boot 1.5.1
security cache control headers written in the DelegatingFilterProxyRegistrationBean, which is sixth in the chain

filterChain = {ApplicationFilterChain@4839} 
 filters = {ApplicationFilterConfig[10]@4978} 
  0 = {ApplicationFilterConfig@4981} "ApplicationFilterConfig[name=errorPageFilter, filterClass=org.springframework.boot.web.support.ErrorPageFilter]"
  1 = {ApplicationFilterConfig@4982} "ApplicationFilterConfig[name=characterEncodingFilter, filterClass=org.springframework.boot.web.filter.OrderedCharacterEncodingFilter]"
  2 = {ApplicationFilterConfig@4983} "ApplicationFilterConfig[name=hiddenHttpMethodFilter, filterClass=org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter]"
  3 = {ApplicationFilterConfig@4984} "ApplicationFilterConfig[name=httpPutFormContentFilter, filterClass=org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter]"
  4 = {ApplicationFilterConfig@4985} "ApplicationFilterConfig[name=requestContextFilter, filterClass=org.springframework.boot.web.filter.OrderedRequestContextFilter]"
  5 = {ApplicationFilterConfig@4986} "ApplicationFilterConfig[name=springSecurityFilterChain, filterClass=org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1]" <- cache control headers written here
  6 = {ApplicationFilterConfig@4987} "ApplicationFilterConfig[name=noCacheFilter, filterClass=com.apixandru.casestudy.NoCacheFilter]"
  7 = {ApplicationFilterConfig@4988} "ApplicationFilterConfig[name=Tomcat WebSocket (JSR356) Filter, filterClass=org.apache.tomcat.websocket.server.WsFilter]"

weblogic spring boot 1.4.4
security cache control headers written after TailFilter, which is last in the chain

filterChain = {FilterChainImpl@22068} 
 filters = {LinkedList@22084}  size = 8
  0 = {NoCacheFilter@22067} 
  1 = {DelegatingFilterProxyRegistrationBean$1@22090} 
  2 = {OrderedRequestContextFilter@22091} 
  3 = {OrderedHttpPutFormContentFilter@22092} 
  4 = {OrderedHiddenHttpMethodFilter@22093} 
  5 = {OrderedCharacterEncodingFilter@22094} 
  6 = {ErrorPageFilter@22095} 
  7 = {TailFilter@22096} <-- cache control headers written here

embedded tomcat spring boot 1.4.4
security cache control headers written after the WsFilter, which is last in the chain

filterChain = {ApplicationFilterChain@4940} 
 filters = {ApplicationFilterConfig[10]@4977} 
  0 = {ApplicationFilterConfig@4980} "ApplicationFilterConfig[name=characterEncodingFilter, filterClass=org.springframework.boot.web.filter.OrderedCharacterEncodingFilter]"
  1 = {ApplicationFilterConfig@4981} "ApplicationFilterConfig[name=hiddenHttpMethodFilter, filterClass=org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter]"
  2 = {ApplicationFilterConfig@4982} "ApplicationFilterConfig[name=httpPutFormContentFilter, filterClass=org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter]"
  3 = {ApplicationFilterConfig@4983} "ApplicationFilterConfig[name=requestContextFilter, filterClass=org.springframework.boot.web.filter.OrderedRequestContextFilter]"
  4 = {ApplicationFilterConfig@4984} "ApplicationFilterConfig[name=springSecurityFilterChain, filterClass=org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1]"
  5 = {ApplicationFilterConfig@4985} "ApplicationFilterConfig[name=noCacheFilter, filterClass=com.apixandru.casestudy.NoCacheFilter]"
  6 = {ApplicationFilterConfig@4986} "ApplicationFilterConfig[name=Tomcat WebSocket (JSR356) Filter, filterClass=org.apache.tomcat.websocket.server.WsFilter]" <-- cache control headers written here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web An issue in web modules (web, webmvc) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants