⚡ 개요
개발 단계에서 발생한 session 이슈가 있어서 해당 내용을 정리 하려고 한다.
운영 단계에서는 발생할 가능성이 적은 내용이며 보안상의 이슈이기 때문에 간단하게만 정리하고 넘어가려고한다.
특정 데이터를 통신 과정에서 유지하기 위해서 session, cookie, token 등 여러가지 방법이 존재한다.
Spring boot session 을 검색만 하더라도 어떻게 구현을 해야하는지도 나온다. 물론 개념적으로 더 알면 좋지만 검색을 하고 따라만 하더라도 개발자 도구에서 쿠키를 확인 해보면 session ID가 들어오고 유지되는 부분을 확인 할수가 있다.
로그인 페이지를 구현하고 테스트 하는 과정에서 계속 session에 저장되지 않고 새로운 session이 생기는 이슈가 발생해서 내용을 정리하게 되었다.
⚡ 이슈 처리 내용
아래의 내용은 session을 저장하고 체크하는 기본적인 샘플 코드이다. (kotlin으로 작업 되어 있음)
controller
@PostMapping("/Login")
fun login(@RequestBody param: String, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any?> {
response.characterEncoding = "UTF-8"
val adminId = paramMap["adminId"].toString()
// 중간 로직 생략
val session: HttpSession = request.session
session.setAttribute("SESSION_ADMIN_KEY", adminId)
logger.info { "sessionValue_Key = " + session.getAttribute("SESSION_ADMIN_KEY") }
logger.info { "sessionKey = " + session.id }
return ResponseEntity<Any?>(result, HttpStatus.OK)
}
Interceptor
@Component
class Interceptor : HandlerInterceptor {
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
if (isEmergencyKey == "true" && !requestURI.equals("/Login")) {
val session: HttpSession? = request.getSession(false)
logger.info { "sessionValue_Key = " + session?.getAttribute("SESSION_ADMIN_KEY") }
logger.info { "sessionKey = " + session?.id }
if (session?.id == null) {
return false
}
}
return true
}
}
위의 코드를 보면 로그인을 할때 session에 adminKey를 담았고, interceptor에서 session을 체크한다.
아마 위의 내용 그대로 작업 하고 호출해보면 잘 될것이다.
내가 안됬던 이유는 Front와 BackEnd url이 달라서 발생한 이슈이다. 😭😭😭
호출 내용의 Header를 보게 되면 아래의 이미지 처럼 Set-Cookie에 경고가 나와있다.
경고 내용이 캡처가 안되서 따로 내용을 가져왔다. (👇👇👇)
This attempt to set a cookie via a Set-Cookie header was blocked because it had the "Secure" attribute but was not received over a secure connection. This attempt to set a cookie via a Set-Cookie header was blocked because it had the "SameSite=Lax" attribute but came from a cross-site response which was not the response to a top-level navigation.
(번역)
Set-Cookie 헤더를 통해 쿠키를 설정하려는 시도는 "Secure" 속성이 있지만 보안 연결을 통해 수신되지 않았기 때문에 차단되었습니다. Set-Cookie 헤더를 통해 쿠키를 설정하려는 시도는 "SameSite=Lax" 속성이 있지만 최상위 탐색에 대한 응답이 아닌 교차 사이트 응답에서 발생했기 때문에 차단되었습니다.
위의 내용에 대해서 확인 해본 결과 Secure 속성이 존재하는 경우, 즉 https에서만 쿠키를 저장 하도록 되어있다.
크롬 기준으로 20년 4월에 나온 크롬 80 버전 부터는 SameSite의 기본값이 None 에서 Lax로 변경되었다고 한다. 개인 정보가 더욱더 중요해지는 만큼 보안도 계속해서 올라가고 있으니 관심을 계속 가지는게 좋다.
그렇다면 왜 크롬은 None 에서 Lax로 바꾼건지를 찾아보았다.
은행 계정을 로그인하고 이 로그인 정보가 토큰으로 관리된다고 하자. 이 경우 악성 스크립트를 통해 특정 계좌로 돈을 입금하는 명령을 보내도록 진행할 수 있다. None인 경우에는 Site에 상관없이 쿠키를 전달하기 때문에 실제로 돈이 입금된다. (이러한 공격을 CSRF 공격이라 한다) 이러한 문제를 막기 위해 크롬에서는 Lax를 기본값으로 설정하여 이미지 요청에 경우만 쿠키를 같이 실어 보내주는 거라고 한다.
# 참고로 강제로 sesure를 ture로 설정하고 테스트 해봤지만 동일하게 쿠키에 sesssion id가 저장되지 않는다.
쿠키 관련 설정은 yml에서 설정이 가능하며 설정 방법에 대해서 밑에 내용을 참고하면 된다.
server:
port: 8080
# servlet:
# session:
# cookie:
# http-only: true
# same-site: lax
# secure: true
⚡ SameSite
SamSIte에는 3가지의 내용이 있고 상황에 맞게 사용하면 된다. (크롬의 기본 설정을 따라가는게 좋다고 생각한다.)
- SameSite=Lax: 쿠키는 동일 사이트에서만 전송되며, 상위 수준의 탐색과 같은 "안전한" 크로스 사이트 요청에서도 전송된다.
- SameSite=Strict: 쿠키는 동일 사이트 요청에서만 전송 된다.
- SameSite=None: 쿠키는 동일 사이트 및 크로스 사이트 요청 모두에서 전송 된다. 하지만 이 속성은 Secure 속성이 있어야 하며 이는 HTTPS를 통해서만 전송될 수 있음을 의미 한다.
위의 내용을 참조해서 개발 할때 당황하지 말자. :)
'Front > Vue' 카테고리의 다른 글
Spring boot + vue 프로젝트 Router 404 이슈 (0) | 2024.06.20 |
---|---|
[Vue] Vue Apollo GraphQL 적용 가이드 (0) | 2024.05.15 |
[FE] Vue 상태 관리 및 라이브러리 정리 (0) | 2022.12.11 |
[FE] Vue 기본 개념 및 기초 내용 정리 (0) | 2022.12.04 |