1

in my situation i have four way to solve my problem:

  1. write meta config in my index.html and disable caching (doesn't work for me)
  2. change index.html to index.jsp and disable caching like here (work for me but my client Group need index.html)
  3. using a filter in web.xml and distinguish the desired request and disable caching
  4. Spring Security

my question is how can i use Spring Security to disable caching for index.html (maybe using intercept-url in http tag)

Community
  • 1
  • 1
Mahdi
  • 748
  • 14
  • 24
  • possible duplicate of [Tomcat: Cache-Control](http://stackoverflow.com/questions/2876250/tomcat-cache-control) – Joe Apr 11 '15 at 03:44
  • You would not normally use Spring Security to adjust caching headers for content. A general servlet filter on `index.html` should solve your problem. – Joe Apr 11 '15 at 03:46

1 Answers1

5

You can selectively add no cache headers to just index.html using Spring Security xml configuartion like this:

<security:http>
[intercept-url, etc omitted...]
        <security:headers>
            <!-- selectively applied to dynamic pages only via pattern matching,  -->
            <security:header ref="noCacheHeaders"/>
        </security:headers>
    </security:http>    

<bean id="noCacheHeaders" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/index.html"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.CacheControlHeadersWriter"/>
        </constructor-arg>
    </bean>

However, the usual pattern if using Spring Security is to set no cache by default to all pages, and then selectively turn those headers off for static resources that

  • don't contain sensitive data
  • aren't dynamic

To accomplish this feat, you have to explicitly define all headers you wish to apply in both cases, and select the pages via complementary request matcher patterns. For example, in an app where static, cacheable resources are found under /static and its subdirectories, and all dynamic pages mapped to controllers have the .htm extension, you can use this configuration:

        <security:http>
[...]
<security:headers>
            <!-- selectively applied to static pages only via pattern matching, see DelegatingRequestMatcherHeaderWriter below-->
            <security:header ref="cacheStaticsHeaders" />

            <!-- selectively applied to dynamic pages only via pattern matching, as above, see below -->
            <security:header ref="xXssProtectionHeader" />
            <security:header ref="noCacheHeaders"/>
            <security:header ref="xContentHeader"/>
            <security:header ref="hstsHeader"/>
            <security:header ref="xFrameHeader"/>
        </security:headers>

    </security:http>


    <!-- set far future caching on static resources -->
    <bean id="cacheStaticsHeaders" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/static/**"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
            <bean class="org.springframework.security.web.header.writers.StaticHeadersWriter">
                <constructor-arg name="headers">
                    <list>
                        <bean class="org.springframework.security.web.header.Header">
                            <constructor-arg name="headerName" value="cache-control"></constructor-arg>
                            <constructor-arg name="headerValues" value="max-age=31536000"/>
                        </bean>
                        <bean class="org.springframework.security.web.header.Header">
                            <constructor-arg name="headerName" value="Expires"></constructor-arg>
                            <constructor-arg name="headerValues" value="31536000"/>
                        </bean>

                    </list>
                </constructor-arg>
            </bean>
        </constructor-arg>
    </bean> 

    <!-- all the following header writers applied to dynamic, shouldn't be cached pages -->
    <bean id="xXssProtectionHeader" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/**/*.htm"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.XXssProtectionHeaderWriter"/>
        </constructor-arg>
    </bean> 
    <bean id="noCacheHeaders" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/**/*.htm"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.CacheControlHeadersWriter"/>
        </constructor-arg>
    </bean> 
        <bean id="xContentHeader" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/**/*.htm"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.XContentTypeOptionsHeaderWriter"/>
        </constructor-arg>
    </bean> 
        <bean id="hstsHeader" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/**/*.htm"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.HstsHeaderWriter"/>
        </constructor-arg>
    </bean> 
        <bean id="xFrameHeader" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
        <constructor-arg>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/**/*.htm"/>
            </bean>
        </constructor-arg>
        <constructor-arg>
                <bean class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
        </constructor-arg>
    </bean> 
slh777
  • 105
  • 2
  • 5
  • This was a life saver - thank you. Used it on Spring Security 3.2.8 / Spring MVC 4.2 - worked exactly as mentioned. – dipan66 Nov 15 '15 at 15:14
  • 1
    I'm using spring security 4.2. After this change, I see the cache control header set twice on static resources:1. Cache-Control:max-age=31536000 cache-control: public 2. Cache-Control:no-cache, no-store, max-age=0, must-revalidate – Prashant Saraswat Dec 18 '16 at 05:35