HttpOnly
JavaScript를 통해 쿠키에 접근할 수 없게 되어, 악성 스크립트를 통해 쿠키 값에 접근하는 것을 막아줌
Secure
Javascript가 아닌 네트워크를 직접 감청하여 쿠키를 가로챌 수도 있음
이러한 정보 유출들을 막기 위해, HTTPS 프로토콜을 사용하여 데이터를 암호화하여 서버에 넘겨주게 되면, 해커들이 쿠키를 탈취해도 암호화가 되어있어 정보를 알아낼 수 없게 됨
이를 위해 Secure 접미사를 사용해서 쿠키를 생성하게 되면 브라우저는 HTTPS 가 아닌 통신에서는 쿠키를 전송하지 않음
// 로그인
// HttpOnly & Secure 쿠키 설정
ResponseCookie cookie = ResponseCookie.from("jwt", token)
.httpOnly(true)
.secure(true) // HTTPS 환경에서만 사용
.path("/")
.maxAge(7 * 24 * 60 * 60) // 7일 유효기간
.sameSite("None") // CSRF 보호
.build();
// 로그아웃
// JWT 쿠키 제거
ResponseCookie cookie = ResponseCookie.from("jwt", null)
.httpOnly(true)
.secure(true) // HTTPS 환경에서만 사용
.path("/")
.maxAge(0) // 즉시 삭제
.sameSite("None")
.build();
// security에 추가해야 하는 옵션
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// CORS 설정 추가
http.cors(cors -> cors.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of(
));
// 쿠키 허용 여부
config.setAllowCredentials(true);
// 쿠키 관련 헤더
config.setExposedHeaders(List.of("Set-Cookie", "X-XSRF-TOKEN"));
}));
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 1. 쿠키에서 토큰 추출
String token = null;
if (request.getCookies() != null) { // Null 체크 추가
token = Arrays.stream(request.getCookies())
.filter(cookie -> "jwt".equals(cookie.getName()))
.findFirst()
.map(Cookie::getValue)
.orElse(null);
}
// 2. 헤더 토큰 추출 로직 간소화
if (token == null) {
token = resolveToken(request);
}
// 3. 인증 처리 로직
try {
if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
return;
}
chain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
이렇게 사용하면 프론트에서 처리해야하는 token 처리를 안해도 됨