feat(platform): add I6 security headers for API chains

Made-with: Cursor
This commit is contained in:
2026-04-06 22:46:31 +08:00
parent 78433faa89
commit d9536802db
@@ -6,15 +6,18 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint; import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
/** /**
* I1JWTBearer)保护业务 APII5{@code /internal/**} 使用内部共享 Token,与 JWT 分离。 * I1JWTBearer)保护业务 APII5{@code /internal/**} 使用内部共享 Token,与 JWT 分离I6:统一安全响应头
*/ */
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@@ -26,6 +29,7 @@ public class SecurityConfig {
HttpSecurity http, InternalTokenAuthenticationFilter internalTokenFilter) throws Exception { HttpSecurity http, InternalTokenAuthenticationFilter internalTokenFilter) throws Exception {
http.securityMatcher("/internal/**") http.securityMatcher("/internal/**")
.csrf(csrf -> csrf.disable()) .csrf(csrf -> csrf.disable())
.headers(this::apiHeaders)
.sessionManagement( .sessionManagement(
sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
@@ -43,6 +47,7 @@ public class SecurityConfig {
public SecurityFilterChain jwtFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtFilter) public SecurityFilterChain jwtFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtFilter)
throws Exception { throws Exception {
http.csrf(csrf -> csrf.disable()) http.csrf(csrf -> csrf.disable())
.headers(this::apiHeaders)
.sessionManagement( .sessionManagement(
sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests( .authorizeHttpRequests(
@@ -66,4 +71,12 @@ public class SecurityConfig {
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build(); return http.build();
} }
/** I6API 最小安全头;HSTS 由边缘 HTTPS 终止(Nginx/Caddy)配置。 */
private void apiHeaders(HeadersConfigurer<HttpSecurity> headers) {
headers
.contentTypeOptions(Customizer.withDefaults())
.frameOptions(frame -> frame.deny())
.referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN));
}
} }