|
1 | | -@Bean |
2 | | -public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
3 | | - http |
4 | | - // Add security headers |
5 | | - .headers(headers -> headers |
6 | | - .contentSecurityPolicy(csp -> csp |
7 | | - .policyDirectives("default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'")) |
8 | | - .referrerPolicy(referrer -> referrer |
9 | | - .policy(org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER)) |
10 | | - .xssProtection(xss -> xss |
11 | | - .block(true)) |
12 | | - .frameOptions(frame -> frame |
13 | | - .deny()) |
14 | | - ) |
15 | | - |
16 | | - // Enable CORS with custom configuration |
17 | | - .cors(Customizer.withDefaults()) |
18 | | - |
19 | | - // Disable CSRF (Cross-Site Request Forgery) protection. |
20 | | - .csrf(csrf -> csrf.disable()) |
21 | | - |
22 | | - // Configure authorization rules for HTTP requests. |
23 | | - .authorizeHttpRequests(authorize -> authorize |
24 | | - .requestMatchers( |
25 | | - "/", "/generate", "/api/generate", "/index", |
26 | | - "/css/**", "/js/**", "/images/**", |
27 | | - "/favicon.ico", "/favicon-16x16.png", "/favicon-32x32.png", |
28 | | - "/apple-touch-icon.png", "/android-chrome-*.png", |
29 | | - "/site.webmanifest", "/robots.txt", |
30 | | - "/download/**" |
31 | | - ).permitAll() |
32 | | - .requestMatchers( |
33 | | - "/wp-admin/**", "/wordpress/**", "/wp-login.php" |
34 | | - ).denyAll() |
35 | | - .anyRequest().authenticated() |
36 | | - ) |
37 | | - |
38 | | - // Disable form-based login and HTTP Basic authentication |
39 | | - .formLogin(formLogin -> formLogin.disable()) |
40 | | - .httpBasic(httpBasic -> httpBasic.disable()) |
41 | | - |
42 | | - // Configure session management to be stateless. |
43 | | - .sessionManagement(session -> session |
44 | | - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
45 | | - ); |
46 | | - |
47 | | - return http.build(); |
| 1 | +package com.keyjolt.config; |
| 2 | + |
| 3 | +import org.springframework.context.annotation.Bean; |
| 4 | +import org.springframework.context.annotation.Configuration; |
| 5 | +import org.springframework.security.config.Customizer; |
| 6 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| 7 | +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
| 8 | +import org.springframework.security.config.http.SessionCreationPolicy; |
| 9 | +import org.springframework.security.core.userdetails.User; |
| 10 | +import org.springframework.security.core.userdetails.UserDetails; |
| 11 | +import org.springframework.security.core.userdetails.UserDetailsService; |
| 12 | +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
| 13 | +import org.springframework.security.crypto.password.PasswordEncoder; |
| 14 | +import org.springframework.security.provisioning.InMemoryUserDetailsManager; |
| 15 | +import org.springframework.security.web.SecurityFilterChain; |
| 16 | +import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; |
| 17 | +import org.springframework.web.cors.CorsConfiguration; |
| 18 | +import org.springframework.web.cors.CorsConfigurationSource; |
| 19 | +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
| 20 | + |
| 21 | +import java.util.List; |
| 22 | + |
| 23 | +@Configuration // Indicates that this class contains Spring configuration |
| 24 | +@EnableWebSecurity // Enables Spring Security's web security support |
| 25 | +public class SecurityConfig { |
| 26 | + |
| 27 | + // Bean for password encoding. |
| 28 | + @Bean |
| 29 | + public PasswordEncoder passwordEncoder() { |
| 30 | + return new BCryptPasswordEncoder(); |
| 31 | + } |
| 32 | + |
| 33 | + // Bean for configuring the security filter chain. |
| 34 | + @Bean |
| 35 | + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
| 36 | + http |
| 37 | + // Enable CORS with custom configuration |
| 38 | + .cors(Customizer.withDefaults()) |
| 39 | + |
| 40 | + // Disable CSRF (Cross-Site Request Forgery) protection. |
| 41 | + .csrf(csrf -> csrf.disable()) |
| 42 | + |
| 43 | + // Configure authorization rules for HTTP requests. |
| 44 | + .authorizeHttpRequests(authorize -> authorize |
| 45 | + .requestMatchers( |
| 46 | + "/", "/generate", "/api/generate", "/index", |
| 47 | + "/css/**", "/js/**", "/images/**", |
| 48 | + "/favicon.ico", "/favicon-16x16.png", "/favicon-32x32.png", |
| 49 | + "/apple-touch-icon.png", "/android-chrome-*.png", |
| 50 | + "/site.webmanifest", "/robots.txt", |
| 51 | + "/download/**" |
| 52 | + ).permitAll() |
| 53 | + .requestMatchers( |
| 54 | + "/wp-admin/**", "/wordpress/**", "/wp-login.php" |
| 55 | + ).denyAll() |
| 56 | + .anyRequest().authenticated() |
| 57 | + ) |
| 58 | + |
| 59 | + // Disable form-based login and HTTP Basic authentication |
| 60 | + .formLogin(formLogin -> formLogin.disable()) |
| 61 | + .httpBasic(httpBasic -> httpBasic.disable()) |
| 62 | + |
| 63 | + // Configure session management to be stateless. |
| 64 | + .sessionManagement(session -> session |
| 65 | + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
| 66 | + ) |
| 67 | + |
| 68 | + // Add hardened security headers |
| 69 | + .headers(headers -> headers |
| 70 | + .httpStrictTransportSecurity(hsts -> hsts |
| 71 | + .includeSubDomains(true) |
| 72 | + .maxAgeInSeconds(31536000)) |
| 73 | + .contentSecurityPolicy(csp -> csp |
| 74 | + .policyDirectives("default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'")) |
| 75 | + .referrerPolicy(referrer -> referrer |
| 76 | + .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER)) |
| 77 | + .xssProtection(Customizer.withDefaults()) |
| 78 | + ); |
| 79 | + |
| 80 | + return http.build(); |
| 81 | + } |
| 82 | + |
| 83 | + // Bean for an in-memory UserDetailsService. |
| 84 | + @Bean |
| 85 | + public UserDetailsService userDetailsService() { |
| 86 | + UserDetails adminUser = User.builder() |
| 87 | + .username("admin") |
| 88 | + .password(passwordEncoder().encode("admin123")) // Password must be encoded |
| 89 | + .roles("ADMIN") // Roles are automatically prefixed with "ROLE_" |
| 90 | + .build(); |
| 91 | + |
| 92 | + return new InMemoryUserDetailsManager(adminUser); |
| 93 | + } |
| 94 | + |
| 95 | + // Bean for CORS configuration |
| 96 | + @Bean |
| 97 | + public CorsConfigurationSource corsConfigurationSource() { |
| 98 | + CorsConfiguration config = new CorsConfiguration(); |
| 99 | + config.setAllowedOrigins(List.of("https://keyjolt.dev", "https://keyjolt.piapps.dev")); |
| 100 | + config.setAllowedMethods(List.of("GET", "POST")); |
| 101 | + config.setAllowedHeaders(List.of("*")); |
| 102 | + config.setAllowCredentials(true); |
| 103 | + |
| 104 | + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
| 105 | + source.registerCorsConfiguration("/**", config); |
| 106 | + return source; |
| 107 | + } |
48 | 108 | } |
0 commit comments