Careeroza
HSTS, Frames and Other Headers
Hardening the Rest
http.headers(headers -> headers
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.preload(true) // eligible for the browser HSTS preload list
.maxAgeInSeconds(Duration.ofDays(365).toSeconds()))
.frameOptions(frame -> frame.deny()) // or sameOrigin() for your own iframes
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN))
.addHeaderWriter(new StaticHeadersWriter("Permissions-Policy",
"camera=(), microphone=(), geolocation=(self), payment=(self)"))
.addHeaderWriter(new StaticHeadersWriter("Cross-Origin-Opener-Policy", "same-origin")));| Header | Why |
|---|---|
Referrer-Policy | stops full URLs (with order ids or reset tokens) leaking to other sites in the Referer header |
Permissions-Policy | turns off browser features you do not use, even if a script is injected |
Cross-Origin-Opener-Policy | isolates your window from pop-ups on other origins |
HTTPS Behind a Load Balancer
HSTS is only sent on HTTPS requests. In production TLS usually ends at the load balancer or Nginx, so the app sees plain HTTP. Tell Spring to trust the proxy's X-Forwarded-Proto header:
application.yml
server:
forward-headers-strategy: framework # or "native" on Tomcat behind a trusted proxyNote: Only enable preload once every subdomain supports HTTPS — after submitting to hstspreload.org, browsers will refuse plain HTTP for your domain for a long time.
Practice
Exercise: The seller portal must be embeddable in an iframe on https://partners.shopease.in only. Which header settings do you use?
Show answer
http.headers(headers -> headers
.frameOptions(frame -> frame.disable()) // X-Frame-Options cannot list other origins
.contentSecurityPolicy(csp -> csp.policyDirectives(
"default-src 'self'; frame-ancestors 'self' https://partners.shopease.in")));