Security headers and HTTPS

Spring Security · lesson 21 of 31 · 3 min read

Know the headers Spring Security already sends, the ones you must add, and how to force HTTPS.

Open this lesson in the learning hub

Key points

  • You already get X-Content-Type-Options: nosniff, X-Frame-Options: DENY and no-cache headers by default.
  • HSTS is only sent over HTTPS. It tells the browser to refuse plain http for your domain for months on end.
  • There is no default Content-Security-Policy. Adding one is the biggest single win against injected script.
  • Behind a proxy set server.forward-headers-strategy=framework, or Spring thinks every request arrived over http.
  • requiresChannel().anyRequest().requiresSecure() redirects http to https instead of trusting the client to do it.
  • Headers are defence in depth. They limit the damage of a bug; they never replace escaping and validation.

Example

http.headers(h -> h
    .frameOptions(f -> f.sameOrigin())                       // only if you frame your own pages
    .httpStrictTransportSecurity(hsts -> hsts
        .includeSubDomains(true)
        .maxAgeInSeconds(31536000))                          // one year
    .contentSecurityPolicy(csp -> csp
        .policyDirectives("default-src 'self'; frame-ancestors 'none'")));

http.requiresChannel(c -> c.anyRequest().requiresSecure());  // http -> https

// application.yml, when a load balancer terminates TLS for you:
//   server.forward-headers-strategy: framework

Sniffing and framing are covered by default; CSP and HSTS are on you.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Security course, and every lesson in it is listed on the Spring Security contents page.