| 1 |
package com.paymentlink.config; |
| 2 |
|
| 3 |
import org.springframework.context.annotation.Bean; |
| 4 |
import org.springframework.context.annotation.Configuration; |
| 5 |
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| 6 |
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
| 7 |
import org.springframework.security.web.SecurityFilterChain; |
| 8 |
import org.springframework.security.web.csrf.CookieCsrfTokenRepository; |
| 9 |
import org.springframework.security.web.csrf.CsrfToken; |
| 10 |
import org.springframework.security.web.firewall.HttpFirewall; |
| 11 |
import org.springframework.security.web.firewall.StrictHttpFirewall; |
| 12 |
import org.springframework.web.cors.CorsConfiguration; |
| 13 |
import org.springframework.web.cors.CorsConfigurationSource; |
| 14 |
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
| 15 |
|
| 16 |
import jakarta.servlet.http.HttpServletRequest; |
| 17 |
import jakarta.servlet.http.HttpServletResponse; |
| 18 |
import org.springframework.security.web.csrf.CsrfTokenRequestHandler; |
| 19 |
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; |
| 20 |
|
| 21 |
import java.util.Arrays; |
| 22 |
import java.util.function.Supplier; |
| 23 |
|
| 24 |
@Configuration |
| 25 |
@EnableWebSecurity |
| 26 |
public class SecurityConfig { |
| 27 |
|
| 28 |
@Bean |
| 29 |
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
| 30 |
http |
| 31 |
|
| 32 |
.authorizeHttpRequests(auth -> auth |
| 33 |
.anyRequest().permitAll() |
| 34 |
) |
| 35 |
|
| 36 |
.csrf(csrf -> csrf.disable()) |
| 37 |
|
| 38 |
.cors(cors -> cors.configurationSource(corsConfigurationSource())); |
| 39 |
|
| 40 |
return http.build(); |
| 41 |
} |
| 42 |
|
| 43 |
|
| 44 |
* Custom CSRF token request handler for SPA |
| 45 |
*/ |
| 46 |
static final class SpaCsrfTokenRequestHandler implements CsrfTokenRequestHandler { |
| 47 |
private final CsrfTokenRequestHandler delegate = new XorCsrfTokenRequestAttributeHandler(); |
| 48 |
|
| 49 |
@Override |
| 50 |
public void handle(HttpServletRequest request, HttpServletResponse response, |
| 51 |
Supplier<CsrfToken> csrfToken) { |
| 52 |
delegate.handle(request, response, csrfToken); |
| 53 |
} |
| 54 |
|
| 55 |
@Override |
| 56 |
public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) { |
| 57 |
String headerValue = request.getHeader(csrfToken.getHeaderName()); |
| 58 |
return (headerValue != null) ? headerValue : delegate.resolveCsrfTokenValue(request, csrfToken); |
| 59 |
} |
| 60 |
} |
| 61 |
|
| 62 |
|
| 63 |
* CORS Configuration |
| 64 |
*/ |
| 65 |
@Bean |
| 66 |
public CorsConfigurationSource corsConfigurationSource() { |
| 67 |
CorsConfiguration configuration = new CorsConfiguration(); |
| 68 |
configuration.setAllowedOrigins(Arrays.asList("*")); |
| 69 |
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); |
| 70 |
configuration.setAllowedHeaders(Arrays.asList("*")); |
| 71 |
configuration.setAllowCredentials(false); |
| 72 |
|
| 73 |
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
| 74 |
source.registerCorsConfiguration("/**", configuration); |
| 75 |
return source; |
| 76 |
} |
| 77 |
|
| 78 |
|
| 79 |
* Custom HTTP Firewall to allow WebDAV methods (PROPFIND, etc.) |
| 80 |
* This prevents RequestRejectedException logs from IDEs like WebStorm |
| 81 |
*/ |
| 82 |
@Bean |
| 83 |
public HttpFirewall allowWebDavHttpFirewall() { |
| 84 |
StrictHttpFirewall firewall = new StrictHttpFirewall(); |
| 85 |
|
| 86 |
|
| 87 |
firewall.setAllowedHttpMethods(Arrays.asList( |
| 88 |
"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD", |
| 89 |
|
| 90 |
"PROPFIND", "PROPPATCH", "REPORT", "LOCK", "UNLOCK", |
| 91 |
"COPY", "MOVE", "MKCOL" |
| 92 |
)); |
| 93 |
|
| 94 |
return firewall; |
| 95 |
} |
| 96 |
} |
| 97 |
|
| 98 |
|