refactor(security): extract static ERROR_WRITER; update ADR ref to ADR-022
Replaces per-invocation new ObjectMapper() in the accessDeniedHandler lambda with a static field (avoids repeated allocation). ObjectMapper cannot be injected in SecurityConfig because @WebMvcTest slices exclude JacksonAutoConfiguration; the static instance is safe since the response only serialises fixed String keys. Also corrects the ADR cross-reference in the CSRF comment from ADR-020 (Spring Session JDBC) to ADR-022 (CSRF + session revocation). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,11 @@ import java.util.Map;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
// @WebMvcTest slices do not include JacksonAutoConfiguration, so ObjectMapper
|
||||||
|
// cannot be injected here. A static instance is safe because the response
|
||||||
|
// only serializes fixed String keys — no custom naming strategy or module needed.
|
||||||
|
private static final ObjectMapper ERROR_WRITER = new ObjectMapper();
|
||||||
|
|
||||||
private final CustomUserDetailsService userDetailsService;
|
private final CustomUserDetailsService userDetailsService;
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
|
|
||||||
@@ -88,7 +93,7 @@ public class SecurityConfig {
|
|||||||
// CSRF protection via CookieCsrfTokenRepository (NFR-SEC-103).
|
// CSRF protection via CookieCsrfTokenRepository (NFR-SEC-103).
|
||||||
// The backend sets an XSRF-TOKEN cookie (not HttpOnly so JS can read it).
|
// The backend sets an XSRF-TOKEN cookie (not HttpOnly so JS can read it).
|
||||||
// All state-changing requests must include X-XSRF-TOKEN matching the cookie.
|
// All state-changing requests must include X-XSRF-TOKEN matching the cookie.
|
||||||
// See ADR-020 and issue #524 for the full security rationale.
|
// See ADR-022 and issue #524 for the full security rationale.
|
||||||
.csrf(csrf -> csrf
|
.csrf(csrf -> csrf
|
||||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||||
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))
|
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))
|
||||||
@@ -127,7 +132,7 @@ public class SecurityConfig {
|
|||||||
ErrorCode code = (e instanceof CsrfException)
|
ErrorCode code = (e instanceof CsrfException)
|
||||||
? ErrorCode.CSRF_TOKEN_MISSING
|
? ErrorCode.CSRF_TOKEN_MISSING
|
||||||
: ErrorCode.FORBIDDEN;
|
: ErrorCode.FORBIDDEN;
|
||||||
res.getWriter().write(new ObjectMapper().writeValueAsString(Map.of("code", code.name())));
|
res.getWriter().write(ERROR_WRITER.writeValueAsString(Map.of("code", code.name())));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
|
|||||||
Reference in New Issue
Block a user