CROS 대응, 토큰 중복 제거.

This commit is contained in:
Hyojin Ahn 2026-06-18 09:30:23 -04:00
parent 3b5cb79f7e
commit 7453e19b2b
3 changed files with 13 additions and 40 deletions

View File

@ -5,6 +5,8 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.http.ResponseCookie;
import org.springframework.http.HttpHeaders;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
@ -54,20 +56,15 @@ public class AuthCookieService {
// ===================== 내부 공통 ===================== // ===================== 내부 공통 =====================
private void addCookie( private void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
HttpServletResponse response, ResponseCookie cookie = ResponseCookie.from(name, value == null ? "" : value)
String name, .httpOnly(true)
String value, .secure(secure)
int maxAge .path(path)
) { .sameSite(sameSite) // Lax / Strict / None
Cookie cookie = new Cookie(name, value); .maxAge(maxAge) // -1 = 세션, 0 = 삭제
cookie.setHttpOnly(true); .build();
cookie.setSecure(secure); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
cookie.setPath(path);
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
addSameSiteAttribute(response, cookie);
} }
private Optional<String> extractCookie(HttpServletRequest request, String name) { private Optional<String> extractCookie(HttpServletRequest request, String name) {
@ -81,29 +78,4 @@ public class AuthCookieService {
.filter(v -> v != null && !v.isBlank()) .filter(v -> v != null && !v.isBlank())
.findFirst(); .findFirst();
} }
/**
* SameSite 수동 세팅 (Servlet Cookie API 한계)
*/
private void addSameSiteAttribute(HttpServletResponse response, Cookie cookie) {
StringBuilder sb = new StringBuilder();
sb.append(cookie.getName()).append("=");
sb.append(cookie.getValue() == null ? "" : cookie.getValue());
sb.append("; Path=").append(cookie.getPath());
sb.append("; HttpOnly");
if (cookie.getSecure()) {
sb.append("; Secure");
}
if (sameSite != null && !sameSite.isBlank()) {
sb.append("; SameSite=").append(sameSite);
}
if (cookie.getMaxAge() == 0) {
sb.append("; Max-Age=0");
}
response.addHeader("Set-Cookie", sb.toString());
}
} }

View File

@ -66,6 +66,7 @@ public class SecurityConfiguration {
CorsConfiguration config = new CorsConfiguration(); CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(List.of( config.setAllowedOriginPatterns(List.of(
"https://portal.greenoilinc.com",
"http://localhost:5173", "http://localhost:5173",
"http://192.168.*.*:5173", "http://192.168.*.*:5173",
"http://10.*.*.*:5173" "http://10.*.*.*:5173"

View File

@ -29,7 +29,7 @@ application:
- "H:R:A" - "H:R:A"
auth: auth:
cookie: cookie:
secure: false # prod: true / local: false secure: true # prod: true / local: false
same-site: Lax # 필요 시 None (→ Secure 필수) same-site: Lax # 필요 시 None (→ Secure 필수)
path: / path: /
server: server: