web-dev-qa-db-ja.com

SpringSecurityヘッダーの無効化が機能しない

Spring Securityconfのキャッシュ制御ヘッダーを無効にする必要があります。

ドキュメントによると、単純なhttp.headers.disable()で実行できますが、それでも

Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Expires:0
Pragma:no-cache

応答のヘッダー。

私の現在のセキュリティ設定は次のとおりです。

http.antMatcher("/myPath/**") // "myPath" is of course not the real path
    .headers().disable()
    .authorizeRequests()
     // ... abbreviated
    .anyRequest().authenticated();

これまでに試したこと:

application.properties

security.headers.cache=false行を追加しましたが、違いはありませんでした。

フィルターを使用

次のフィルターを試しました。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
      @Override
      public void setHeader(String name, String value) {
        if (name.equalsIgnoreCase("Cache-Control")) {
          value = "";
        } else if (name.equalsIgnoreCase("Expires")) {
          value = "";
        } else if (name.equalsIgnoreCase("Pragma")) {
          value = "";
        }
        super.setHeader(name, value);
      }
  });
}

ロギングを追加した後、このフィルターはX-XSS-Protectionヘッダーのみを書き込み、すべてのキャッシュヘッダーは後でどこかに書き込まれ、このフィルターはそれらを「オーバーライド」するアクセス権を持たないことがわかりました。これは、セキュリティフィルターチェーンの最後の位置にこのフィルターを追加した場合でも発生します。

インターセプターを使用

次のインターセプターを試しました。

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    String requestUri = request.getRequestURI();
    response.setHeader("Cache-Control", "max-age=3600");
    response.setHeader("Expires", "3600");
    response.setHeader("Pragma", "");
}

これは(かなり予想通りに)ヘッダーを追加しただけです。つまり、インターセプターによって追加されたヘッダーに加えて、元のno-cacheヘッダーが引き続き表示されます。

私はここで私の知恵の終わりにいます。 Springセキュリティによって設定されたキャッシュ制御ヘッダーを削除するにはどうすればよいですか?

17
j0ntech

それは助けになるかもしれません:

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .defaultsDisabled()
        .cacheControl();
}
}

http://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html#headers-cache-control

5
Colin Shah

フィルタと認証プロバイダーを構成するために、2つのオーバーライドされたconfigureメソッドを使用して WebSecurityConfigurerAdapter を拡張するクラスが必要になります。たとえば、以下は最低限でも機能します。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfigDemo extends WebSecurityConfigurerAdapter {

    @Autowired
    private DemoAuthenticationProvider demoAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {        

    // Prevent the HTTP response header of "Pragma: no-cache".
    http.headers().cacheControl().disable();

    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {        
        auth.authenticationProvider(demoAuthenticationProvider);        
    }    

}

次のように、パブリック静的リソースに対してSpring Securityを完全に無効にすることもできます(上記と同じクラス)。

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/static/public/**");
}

これには、キャッシュ制御ヘッダーを正しく取得するために2つのリソースハンドラーを構成する必要があります。

@Configuration
public class MvcConfigurer extends WebMvcConfigurerAdapter
        implements EmbeddedServletContainerCustomizer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // Resources without Spring Security. No cache control response headers.
        registry.addResourceHandler("/static/public/**")
            .addResourceLocations("classpath:/static/public/");

        // Resources controlled by Spring Security, which
        // adds "Cache-Control: must-revalidate".
        registry.addResourceHandler("/static/**")
            .addResourceLocations("classpath:/static/")
            .setCachePeriod(3600*24);
    }
}
1
SkyWalker

アプリケーションクラスで@EnableOAuth2Ssoを介してOpenIdConnectを有効にした後、この問題が発生しました。デバッグとドキュメントの閲覧を約6時間行った後、@EnableOAuth2SsoWebSecurityConfigurerAdapterに配置する必要があることが判明しました。そうしないと、カスタム設定がデフォルト設定で上書きされます。

良い

// In Application.Java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

//In WebSecurity.Java
@Configuration
@EnableOAuth2Sso  // <- This MUST be here, not above
public class WebSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().disable();
    }
}

悪い

// In Application.Java
@SpringBootApplication
@EnableOAuth2Sso  // <- Will overwrite config below
public class Application {
    //...
}

@Configuration
public class WebSecurity extends WebSecurityConfigurerAdapter {
    //...
}
1
ikh

それで、私は自分で答えを見つけました。私はついにCache-Controlヘッダーを作成して、yml構成ファイルにspring.resources.cachePeriodという新しいエントリを作成し、それを0とは異なる値に設定して値を変更しました。悪い点は、すべてのリソースがこの設定を使用することです。したがって、私が知る限り、リソースによって異なる設定にする方法はありません。

この質問 への答えは大いに役立ちました。

1
Pedro Madrid

したがって、同様の問題が発生し、ほとんどのRESTエンドポイントにSpringが挿入する標準の「キャッシュしない」ヘッダーを持たせたいのですが、1つのエンドポイントに独自のヘッダーを挿入したいと思います。

ResponseEntryに指定するHttpHeadersオブジェクトで独自の指定を行うことはできません。

動作するのは、HttpServletResponseに直接ヘッダーを明示的に設定することです。

Springは「Cache-Control」、「Pragma」、「Expires」を設定しています。以下は、1分間のキャッシュをオーバーライドして設定する方法を示しています。

response.setHeader("Cache-Control", "max-age=60");
response.setHeader("Pragma", "");
HttpHeaders headers = new HttpHeaders();
headers.setExpires(System.currentTimeMillis()+60000);
return new ResponseEntity<>(body, headers, HttpStatus.OK);
0
BrianT.