110 lines
3.3 KiB
Java
110 lines
3.3 KiB
Java
package com.goi.erp.auth;
|
|
|
|
import jakarta.servlet.http.Cookie;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Optional;
|
|
|
|
@Service
|
|
public class AuthCookieService {
|
|
|
|
public static final String AUTH_COOKIE_NAME = "AUTH_TOKEN";
|
|
public static final String REFRESH_COOKIE_NAME = "REFRESH_TOKEN";
|
|
|
|
@Value("${auth.cookie.secure:true}")
|
|
private boolean secure;
|
|
|
|
@Value("${auth.cookie.same-site:Lax}")
|
|
private String sameSite;
|
|
|
|
@Value("${auth.cookie.path:/}")
|
|
private String path;
|
|
|
|
// ===================== Access Token =====================
|
|
|
|
public void addAuthCookie(HttpServletResponse response, String jwt) {
|
|
addCookie(response, AUTH_COOKIE_NAME, jwt, -1);
|
|
}
|
|
|
|
public void clearAuthCookie(HttpServletResponse response) {
|
|
addCookie(response, AUTH_COOKIE_NAME, null, 0);
|
|
}
|
|
|
|
public Optional<String> extractJwt(HttpServletRequest request) {
|
|
return extractCookie(request, AUTH_COOKIE_NAME);
|
|
}
|
|
|
|
// ===================== Refresh Token =====================
|
|
|
|
public void addRefreshCookie(HttpServletResponse response, String refreshToken) {
|
|
addCookie(response, REFRESH_COOKIE_NAME, refreshToken, -1);
|
|
}
|
|
|
|
public void clearRefreshCookie(HttpServletResponse response) {
|
|
addCookie(response, REFRESH_COOKIE_NAME, null, 0);
|
|
}
|
|
|
|
public Optional<String> extractRefreshToken(HttpServletRequest request) {
|
|
return extractCookie(request, REFRESH_COOKIE_NAME);
|
|
}
|
|
|
|
// ===================== 내부 공통 =====================
|
|
|
|
private void addCookie(
|
|
HttpServletResponse response,
|
|
String name,
|
|
String value,
|
|
int maxAge
|
|
) {
|
|
Cookie cookie = new Cookie(name, value);
|
|
cookie.setHttpOnly(true);
|
|
cookie.setSecure(secure);
|
|
cookie.setPath(path);
|
|
cookie.setMaxAge(maxAge);
|
|
|
|
response.addCookie(cookie);
|
|
addSameSiteAttribute(response, cookie);
|
|
}
|
|
|
|
private Optional<String> extractCookie(HttpServletRequest request, String name) {
|
|
if (request.getCookies() == null) {
|
|
return Optional.empty();
|
|
}
|
|
|
|
return Arrays.stream(request.getCookies())
|
|
.filter(c -> name.equals(c.getName()))
|
|
.map(Cookie::getValue)
|
|
.filter(v -> v != null && !v.isBlank())
|
|
.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());
|
|
}
|
|
}
|