.requestMatchers("/member/signup")
.hasAuthority("PRE_MEMBER")hasAuthority() 을 사용할 수 있고, hasRole()을 사용할 수도 있는데, hasRole() 의 경우 접두사로 "ROLE_"을 자동으로 붙여 비교하기 때문에 hasAuthority() 을 사용하였다.{
"sub": "42239~~",
"role": "PRE_MEMBER",
"iat": 1746516973,
"exp": 1746524173
}{
"sub": "42239~~~",
"role": "MEMBER",
"iat": 1746516973,
"exp": 1746524173
}sameSite() 설정sameStie() 설정을 해줘야 하는데 처음에는 다음과 같이 쿠키를 발급했다.ResponseCookie accessCookie = ResponseCookie.from("access", token)
.httpOnly(true)
.path("/")
.sameSite("Strict")
.maxAge(Duration.ofHours(2))
.build();
.sameSite("Strict") 을 사용하면 서로 다른 도메인에서 쿠키 전송이 아예 되지 않는다. 따라서 이렇게 설정하면 안된다. .sameSite("Lax") 값으로 설정했다 (Chrome에서는 기본값이 "Lax" 이기 때문에 따로 설정하지 않았다)ResponseCookie accessCookie = ResponseCookie.from("access", token)
.httpOnly(true)
.path("/")
// sameSite을 따로 설정하지 않고 기본값으로 둔다.
.maxAge(Duration.ofHours(2))
.build();
.sameSite("None") 이었다. 하지만 이는 반드시 .secure(true) 설정이 필요했고, 이는 HTTPS 가 필요하다는 것을 의미했다.return ResponseCookie.from(key, value)
.httpOnly(true)
.path("/")
.sameSite("None")
.secure(true)
.maxAge(Duration.ofHours(2))
.build();
명시적으로 프론트엔드와 백엔드에서 HTTPS 가 필요한 이유는 다음과 같다.
- 프론트가 브라우저가 보안 경로(HTTPS) 아니면 SameSite=None 쿠키를 아예 차단함.
- 백엔드가 Set-Cookie 헤더를 받을 때 Secure 쿠키 전송하려면 HTTPS 통신이어야 함
따라서 AWS EC2 에 HTTP로 배포된 내 서버를 HTTPS로 배포해야 되는 것이었다.
가비아에서 적당한 도메인을 하나 골라서 이를 사용해서 배포하였다.
이제는 되겠지? 하지만 아직 안된다... 왜 안되는데?
public static ResponseCookie createCookie(String key, String value) {
return ResponseCookie.from(key, value)
.httpOnly(true)
.path("/")
.sameSite("None")
.secure(true)
.domain(".morak.vercel.app")
.maxAge(Duration.ofHours(2))
.build();
}
public static ResponseCookie createCookie(String key, String value) {
return ResponseCookie.from(key, value)
.httpOnly(true)
.path("/")
.sameSite("None")
.secure(true)
.domain(".morak.site")
.maxAge(Duration.ofHours(2))
.build();
}
OPTIONS 을 사용한다.OPTIONS 요청에 대해서는 인증, 인가 작업이 이루어지고 있어 쿠키 전송이 안되는 것이었다!!OPTIONS 요청은 인증, 인가 과정이 이뤄지지 않도록 예외 처리를 해주었다.// 커스텀 필터에서 인증 예외 처리하기
@Override
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response,
@NotNull FilterChain filterChain)
throws ServletException, IOException {
String requestURI = request.getRequestURI();
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
filterChain.doFilter(request, response);
return;
}
...
// 인가 예외 처리하기
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.sameSite("None").secure(true) 설정을 반드시 사용할 것.