처음에 cookie는 다음과 받은 방법으로 브라우저에 세팅하고 있었다.
public static void addCookie(HttpServletResponse response, String name, String value, int maxAge, String domain) {
ResponseCookie cookie = ResponseCookie.from(name, value)
.maxAge(maxAge)
.domain(domain)
.path("/")
.build();
response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
}
HTTP 쿠키는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각이다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송한다. 쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다. 이를 이용하면 사용자의 로그인 상태를 유지할 수 있다. 상태가 없는(stateless) HTTP 프로토콜에서 상태 정보를 기억시켜주기 때문이다.
쿠키는 주로 세 가지 목적을 위해 사용된다:
세션 관리(Session management)
서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리
개인화(Personalization)
사용자 선호, 테마 등의 세팅
트래킹(Tracking)
사용자 행동을 기록하고 분석하는 용도
| 여기서 주의해야할 점은 Cookie는 브라우저에 저장되기 때문에 민감한 정보를 보관하면 안된다
어떻게 보면 단순하게 Cookie를 브라우저에 set하고 브라우저는 해당 서버에 요청을 보낼 때마다 Cookie를 보내주는 것으로 간단해 보이지만 보안적인 측면이 적용되면 복잡해진다. 쿠키에 다음과 같은 속성을 알아보자
Domain이라는 속성은 쿠키를 수신할 수 있는 서버를 지정한다.
Domain을 지정하면 해당 서버와 해당 하위 도메인에서 쿠키를 사용할 수 있다. 예를 들어 Domain=mozilla.org로 설정하면 mozilla.org와 그 하위 도메인(예: developer.mozilla.org)에서 쿠키를 사용할 수 있다.
만약 쿠키를 사용하는 서버가 mail.naver.com, naver.com, shopping.naver.com 등 여러개라면 Domain 속성을 활용하여 여러 서버에서 Cookie를 공유하고 로그인 세션을 유지할 수 있다.
퍼스트 파트 쿠키와 서드 파티 쿠키는 다음과 같은 예시로 설명 가능하다.
만약 naver.com 에 접속하였을때 naver 사이트는 이미지를 가져오기 위해 다른 example.com 이라는 사이트에 이미지를 가져오는 요청을 할 수도 있다.
이때 사용자가 example.com에 대한 쿠키를 가지고있다면 이 쿠키가 전송되고 이를 서드 파티 쿠키라고 한다. 여기서 퍼스트 파티 쿠키는 naver.com의 쿠키로 사용자가 접속한 사이트의 쿠키를 의미한다. 만약 사용자가 example.com에 접속했다면 example.com에 설정된 쿠키는 naver.com에 접속했을 때 서드 파티 쿠키지만 지금은 퍼스트 파티 쿠기가 된다.
Cookie의 Path 속성을 이용하면 서버의 특정 URL에 대해서만 쿠키를 전송할 수 있다 path 속성은 디렉터리 단위로 지정 가능하다.
예를 들어 Path=/docs를 설정하면 다음 경로에 쿠키를 전송한다.
쿠키에 별도로 설정을 가하지 않는다면, 브라우저들은 모든 HTTP 요청에 대해서 쿠키를 전송한다. 이는 CSRF 취약점을 만들어낸다. CSRF 공격은 다음과 같은 방식이다.
SameSite속성을 사용하면 서버가 쿠키를 cross-site간에 전송할지 말지 결정할 수 있다. 이를 통해CSRF 공격을 어느 정도 방지할 수 있다. 속성 종류로는 None, Lax, Strict세 가지 종류를 선택할 수 있다
Lax 서드 파티 쿠키가 전송되는 경우
같은 웹 사이트일때는 당연히 전송되고, 이외에는 Top Level Navigation(웹 페이지 이동)과, "안전한" HTTP 메서드 요청에 경우 전송된다.
Top Level Navigation에는 유저가 링크 를 클릭하거나, window.location.replace 등으로 인해 자동으로 이뤄지는 이동, 302 리다이렉트를 이용한 이동이 포함된다. 하지만 iframe이나 img를 문서에 삽입함으로서 발생하는 HTTP 요청은 "Navigation"이라고 할 수 없으니 Lax 쿠키가 전송되지 않고, iframe 안에서 페이지를 이동하는 경우는 "Top Level"이라고 할 수 없으므로 Lax 쿠키는 전송되지 않는다.
또한 "안전하지 않은" POST나 DELETE 같은 요청의 경우, Lax 쿠키는 전송되지 않는다. 하지만 GET처럼 서버의 서버의 상태를 바꾸지 않을 거라고 기대되는 요청에는 Lax 쿠키가 전송됨.
secure이 적용된 쿠키는 HTTPS 요청에만 전송되는 쿠키이다. chrome에서는 secure속성이 적용되어있지 않은 쿠키의 SameSite=None 속성을 허용하지 않는다.
httpOnly 속성을 사용하면 js로 cookie에 접근하는 것을 예방할 수 있다.
public void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
String domain = applicationYmlRead.getDomain();
ResponseCookie cookie = ResponseCookie.from(name, value)
.maxAge(maxAge)
.domain(domain)
.httpOnly(false)
.path("/")
.secure(true)
.build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
}