diff --git a/6-data-storage/01-cookie/article.md b/6-data-storage/01-cookie/article.md index de532a1b4..13f684fdc 100644 --- a/6-data-storage/01-cookie/article.md +++ b/6-data-storage/01-cookie/article.md @@ -1,39 +1,23 @@ # 쿠키와 document.cookie -<<<<<<< HEAD 쿠키는 브라우저에 저장되는 작은 크기의 문자열로, [RFC 6265](https://tools.ietf.org/html/rfc6265) 명세에서 정의한 HTTP 프로토콜의 일부입니다. -쿠키는 주로 웹 서버에 의해 만들어집니다. 서버가 HTTP 응답 헤더(header)의 `Set-Cookie`에 내용을 넣어 전달하면, 브라우저는 이 내용을 자체적으로 브라우저에 저장합니다. 이게 바로 쿠키입니다. 브라우저는 사용자가 쿠키를 생성하도록 한 동일 서버(사이트)에 접속할 때마다 쿠키의 내용을 `Cookie` 요청 헤더에 넣어서 함께 전달합니다. -======= -Cookies are small strings of data that are stored directly in the browser. They are a part of the HTTP protocol, defined by the [RFC 6265](https://tools.ietf.org/html/rfc6265) specification. - -Cookies are usually set by a web server using the response `Set-Cookie` HTTP header. Then, the browser automatically adds them to (almost) every request to the same domain using the `Cookie` HTTP header. ->>>>>>> upstream/master +쿠키는 주로 웹 서버에 의해 만들어집니다. 서버가 HTTP 응답 헤더의 `Set-Cookie`에 내용을 넣어 전달하면, 브라우저는 이 내용을 저장합니다. 이게 바로 쿠키입니다. 이후 브라우저는 같은 도메인에 요청을 보낼 때마다 쿠키의 내용을 `Cookie` 요청 헤더에 넣어 함께 전달합니다. 쿠키는 클라이언트 식별과 같은 인증에 가장 많이 쓰입니다. -<<<<<<< HEAD -1. 사용자가 로그인하면 서버는 HTTP 응답 헤더의 `Set-Cookie`에 담긴 "세션 식별자(session identifier)" 정보를 사용해 쿠키를 설정합니다. -2. 사용자가 동일 도메인에 접속하려고 하면 브라우저는 HTTP `Cookie` 헤더에 인증 정보가 담긴 고윳값(세션 식별자)을 함께 실어 서버에 요청을 보냅니다. +1. 사용자가 로그인하면 서버는 HTTP 응답 헤더의 `Set-Cookie`에 담긴 "세션 식별자" 정보를 사용해 쿠키를 설정합니다. +2. 사용자가 동일 도메인에 접속하려고 하면 브라우저는 HTTP `Cookie` 헤더에 인증 정보가 담긴 고윳값인 세션 식별자를 함께 실어 서버에 요청을 보냅니다. 3. 서버는 브라우저가 보낸 요청 헤더의 세션 식별자를 읽어 사용자를 식별합니다. -======= -1. Upon sign-in, the server uses the `Set-Cookie` HTTP header in the response to set a cookie with a unique "session identifier". -2. Next time the request is sent to the same domain, the browser sends the cookie over the net using the `Cookie` HTTP header. -3. So the server knows who made the request. ->>>>>>> upstream/master `document.cookie` 프로퍼티를 이용하면 브라우저에서도 쿠키에 접근할 수 있습니다. -<<<<<<< HEAD 쿠키와 다양한 쿠키의 옵션을 다루는 일은 쉽지 않습니다. 이 챕터에선 이에 대해 자세히 알아보도록 하겠습니다. -======= -There are many tricky things about cookies and their attributes. In this chapter, we'll cover them in detail. ->>>>>>> upstream/master ## 쿠키 읽기 ```online -지금 보고 있는 이 사이트와 관련된 쿠키가 브라우저에 저장되어있는지 알아봅시다. +지금 보고 있는 이 사이트와 관련된 쿠키가 브라우저에 저장되어 있는지 알아봅시다. ``` ```offline @@ -41,37 +25,23 @@ There are many tricky things about cookies and their attributes. In this chapter ``` ```js run -// javascript.info에선 Google Analytics(GA)를 사용해 데이터를 수집하고 있습니다. +// javascript.info에선 Google Analytics를 사용해 데이터를 수집하고 있습니다. // 이와 관련된 쿠키를 확인해 봅시다. alert( document.cookie ); // cookie1=value1; cookie2=value2;... ``` -<<<<<<< HEAD -`document.cookie`는 `name=value` 쌍으로 구성되어있고, 각 쌍은 `;`로 구분합니다. 이때, 쌍 하나는 하나의 독립된 쿠키를 나타냅니다. +`document.cookie`는 `name=value` 쌍으로 구성되어 있고, 각 쌍은 `;`로 구분합니다. 이때, 쌍 하나는 하나의 독립된 쿠키를 나타냅니다. `;`을 기준으로 `document.cookie`의 값을 분리하면 원하는 쿠키를 찾을 수 있습니다. 정규 표현식이나 배열 관련 함수를 함께 사용해서 말이죠. -이에 관한 연습문제를 아래에서 풀어보길 권유합니다. 쿠키 조작에 쓰이는 몇 가지 헬퍼(도우미) 함수를 챕터 끝에 명시해 놓았으니, 이를 참고하셔도 좋습니다. -======= -The value of `document.cookie` consists of `name=value` pairs, delimited by `; `. Each one is a separate cookie. - -To find a particular cookie, we can split `document.cookie` by `; `, and then find the right name. We can use either a regular expression or array functions to do that. - -We leave it as an exercise for the reader. Also, at the end of the chapter, you'll find helper functions to manipulate cookies. ->>>>>>> upstream/master +이에 관한 연습문제를 아래에서 풀어보길 권유합니다. 쿠키 조작에 쓰이는 몇 가지 도우미 함수를 챕터 끝에 명시해 놓았으니, 이를 참고하셔도 좋습니다. ## 쿠키 쓰기 -<<<<<<< HEAD -`document.cookie`에 직접 값을 쓸 수 있습니다. 이때 `cookie`는 데이터 프로퍼티가 아닌 접근자(accessor) 프로퍼티입니다. 앞서 에서 학습한 바와 같이, 접근자 프로퍼티에 값을 할당하는 것은 데이터 프로퍼티에 값을 할당하는 것과는 조금 다르게 처리됩니다. +`document.cookie`에 직접 값을 쓸 수 있습니다. 이때 `cookie`는 데이터 프로퍼티가 아닌 접근자 프로퍼티입니다. 앞서 에서 학습한 바와 같이, 접근자 프로퍼티에 값을 할당하는 것은 데이터 프로퍼티에 값을 할당하는 것과는 조금 다르게 처리됩니다. **`document.cookie`에 값을 할당하면, 브라우저는 이 값을 받아 해당 쿠키를 갱신합니다. 이때, 다른 쿠키의 값은 변경되지 않습니다.** -======= -We can write to `document.cookie`. But it's not a data property, it's an [accessor (getter/setter)](info:property-accessors). An assignment to it is treated specially. - -**A write operation to `document.cookie` updates only the cookie mentioned in it and doesn't touch other cookies.** ->>>>>>> upstream/master 아래와 같이 코드를 작성하면 이름이 `user`인 쿠키를 찾아 그 값을 `John`으로 갱신합니다. @@ -80,21 +50,12 @@ document.cookie = "user=John"; // 이름이 'user'인 쿠키의 값만 갱신함 alert(document.cookie); // 모든 쿠키 보여주기 ``` -<<<<<<< HEAD 코드를 실행하면 여러 개의 쿠키가 출력되는 것을 확인할 수 있습니다. 이를 통해 `document.cookie=` 연산은 모든 쿠키를 덮어쓰지 않고, 명시된 쿠키인 `user`의 값만 갱신한 것을 알 수 있습니다. 쿠키의 이름과 값엔 특별한 제약이 없기 때문에 모든 글자가 허용됩니다. 하지만 형식의 유효성을 일관성 있게 유지하기 위해 반드시 내장 함수 `encodeURIComponent`를 사용하여 이름과 값을 이스케이프 처리해 줘야 합니다. ```js run -// 특수 값(공백)은 인코딩 처리해 줘야 합니다. -======= -If you run it, you will likely see multiple cookies. That's because the `document.cookie=` operation does not overwrite all cookies. It only sets the mentioned cookie `user`. - -Technically, name and value can have any characters. To keep the valid formatting, they should be escaped using a built-in `encodeURIComponent` function: - -```js run -// special characters (spaces) need encoding ->>>>>>> upstream/master +// 공백 같은 특수 값은 인코딩 처리해 줘야 합니다. let name = "my name"; let value = "John Smith" @@ -105,9 +66,9 @@ alert(document.cookie); // ...; my%20name=John%20Smith ``` -<<<<<<< HEAD ```warn header="쿠키의 한계" 쿠키엔 몇 가지 제약 사항이 있습니다. +- `document.cookie`를 사용하면 한 번에 쿠키 하나만 설정하거나 갱신할 수 있습니다. - `encodeURIComponent`로 인코딩한 이후의 `name=value` 쌍은 4KB를 넘을 수 없습니다. 이 용량을 넘는 정보는 쿠키에 저장할 수 없습니다. - 도메인 하나당 저장할 수 있는 쿠키의 개수는 20여 개 정도로 한정되어 있습니다. 개수는 브라우저에 따라 조금씩 다릅니다. ``` @@ -115,95 +76,43 @@ alert(document.cookie); // ...; my%20name=John%20Smith 쿠키엔 몇 가지 옵션이 있습니다. 몇몇 옵션은 아주 중요하기 때문에 꼭 지정해 줘야 합니다. 옵션은 `key=value` 뒤에 나열하고 `;`로 구분합니다. 아래와 같이 말이죠. -======= -```warn header="Limitations" -There are a few limitations: -- You can only set/update a single cookie at a time using `document.cookie`. -- The `name=value` pair, after `encodeURIComponent`, should not exceed 4KB. So we can't store anything huge in a cookie. -- The total number of cookies per domain is limited to around 20+, the exact limit depends on the browser. -``` - -Cookies have several attributes, many of which are important and should be set. - -The attributes are listed after `key=value`, delimited by `;`, like this: ->>>>>>> upstream/master ```js run document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT" ``` -<<<<<<< HEAD -## path - -- **`path=/mypath`** - -URL path(경로)의 접두사로, 이 경로나 이 경로의 하위 경로에 있는 페이지만 쿠키에 접근할 수 있습니다. 절대 경로이어야 하고, (미 지정시) 기본값은 현재 경로입니다. - -`path=/admin` 옵션을 사용하여 설정한 쿠키는 `/admin`과 `/admin/something`에선 볼 수 있지만, `/home` 이나 `/adminpage`에선 볼 수 없습니다. - -특별한 경우가 아니라면, `path` 옵션을 `path=/`같이 루트로 설정해 웹사이트의 모든 페이지에서 쿠키에 접근할 수 있도록 합시다. - -======= ->>>>>>> upstream/master ## domain - **`domain=site.com`** -<<<<<<< HEAD -쿠키에 접근 가능한 domain(도메인)을 지정합니다. 다만, 몇 가지 제약이 있어서 아무 도메인이나 지정할 수 없습니다. +쿠키에 접근 가능한 `domain`을 지정합니다. 다만, 몇 가지 제약이 있어서 아무 도메인이나 지정할 수 없습니다. + +**다른 2단계 도메인에서 쿠키에 접근하게 할 방법은 없습니다. 따라서 `other.com`은 `site.com`에서 설정한 쿠키를 절대 받지 못합니다.** -`domain` 옵션에 아무 값도 넣지 않았다면, 쿠키를 설정한 도메인에서만 쿠키에 접근할 수 있습니다. `site.com`에서 설정한 쿠키는 `other.com`에서 얻을 수 없죠. +이런 제약사항은 안전성을 높이기 위해 만들어졌습니다. 민감한 데이터가 저장된 쿠키는 관련 페이지에서만 볼 수 있도록 하기 위해서 말이죠. -이 외에 까다로운 제약사항이 하나 더 있습니다. 서브 도메인(subdomain)인 `forum.site.com`에서도 쿠키 정보를 얻을 수 없다는 점입니다. +기본적으로 쿠키는 쿠키를 설정한 도메인에서만 접근할 수 있습니다. + +기본적으로 쿠키는 `forum.site.com` 같은 서브 도메인과 공유되지 않는다는 점에 유의하세요. ```js // site.com에서 쿠키를 설정함 document.cookie = "user=John" -// site.com의 서브도메인인 forum.site.com에서 user 쿠키에 접근하려 함 +// site.com의 서브 도메인인 forum.site.com에서 user 쿠키에 접근하려 함 alert(document.cookie); // 찾을 수 없음 ``` -======= -A domain defines where the cookie is accessible. In practice though, there are limitations. We can't set any domain. ->>>>>>> upstream/master -**서브 도메인이나 다른 도메인에서 쿠키에 접속할 방법은 없습니다. `site.com`에서 생성한 쿠키를 `other.com`에선 절대 전송받을 수 없습니다.** +...하지만 변경할 수 있습니다. `forum.site.com` 같은 서브 도메인이 `site.com`에서 설정한 쿠키를 가져오도록 허용하고 싶다면 가능합니다. -<<<<<<< HEAD -이런 제약사항은 안정성을 높이기 위해 만들어졌습니다. 민감한 데이터가 저장된 쿠키는 관련 페이지에서만 볼 수 있도록 하기 위해서 말이죠. +그렇게 하려면 `site.com`에서 쿠키를 설정할 때 `domain` 속성을 루트 도메인인 `domain=site.com`으로 명시적으로 설정해야 합니다. 그러면 모든 서브 도메인에서 해당 쿠키를 볼 수 있습니다. -그런데 정말 `forum.site.com`과 같은 서브 도메인에서 `site.com`에서 생성한 쿠키 정보를 얻을 방법이 없는 걸까요? 방법이 있습니다. `site.com`에서 쿠키를 설정할 때 `domain` 옵션에 루트 도메인인 `domain=site.com`을 명시적으로 설정해 주면 되죠. +예를 들어: ```js // site.com에서 -// 서브 도메인(*.site.com) 어디서든 쿠키에 접속하게 설정할 수 있습니다. -document.cookie = "user=John; domain=site.com" -======= -It's a safety restriction, to allow us to store sensitive data in cookies that should be available only on one site. - -By default, a cookie is accessible only at the domain that set it. - -Please note, by default, a cookie is not shared with a subdomain, such as `forum.site.com`. - -```js -// if we set a cookie at site.com website... -document.cookie = "user=John" - -// ...we won't see it at forum.site.com -alert(document.cookie); // no user -``` - -...But this can be changed. If we'd like to allow subdomains like `forum.site.com` to get a cookie set at `site.com`, that's possible. - -For that to happen, when setting a cookie at `site.com`, we should explicitly set the `domain` attribute to the root domain: `domain=site.com`. Then all subdomains will see such a cookie. - -For example: - -```js -// at site.com -// make the cookie accessible on any subdomain *.site.com: +// 서브 도메인 *.site.com 어디서든 쿠키에 접근할 수 있게 합니다. document.cookie = "user=John; *!*domain=site.com*/!*" ->>>>>>> upstream/master // 이렇게 설정하면 @@ -211,51 +120,33 @@ document.cookie = "user=John; *!*domain=site.com*/!*" alert(document.cookie); // user=John 쿠키를 확인할 수 있습니다. ``` -<<<<<<< HEAD -하위 호환성 유지를 위해 (`site.com` 앞에 점을 붙인) `domain=.site.com`도 `domain=site.com`과 동일하게 작동합니다. 오래된 표기법이긴 하지만 구식 브라우저를 지원하려면 이 표기법을 사용하는 것이 좋습니다. - -이렇게 `domain` 옵션값을 적절히 사용하면 서브 도메인에서도 쿠키에 접근할 수 있습니다. -======= -```warn header="Legacy syntax" -Historically, `domain=.site.com` (with a dot before `site.com`) used to work the same way, allowing access to the cookie from subdomains. Leading dots in domain names are now ignored, but some browsers may decline to set the cookie containing such dots. +```warn header="레거시 문법" +예전에는 (`site.com` 앞에 점을 붙인) `domain=.site.com`도 `domain=site.com`과 동일하게 동작해 서브 도메인에서 쿠키에 접근할 수 있게 했습니다. 이제 도메인 이름 앞의 점은 무시되지만, 일부 브라우저는 이런 점이 포함된 쿠키 설정을 거부할 수 있습니다. ``` -To summarize, the `domain` attribute allows to make a cookie accessible at subdomains. +이렇게 `domain` 옵션값을 적절히 사용하면 서브 도메인에서도 쿠키에 접근할 수 있습니다. ## path - **`path=/mypath`** -The URL path prefix must be absolute. It makes the cookie accessible for pages under that path. By default, it's the current path. +URL 경로의 접두사입니다. 이 경로나 이 경로의 하위 경로에 있는 페이지만 쿠키에 접근할 수 있습니다. 절대 경로이어야 하고, 미지정 시 기본값은 현재 경로입니다. -If a cookie is set with `path=/admin`, it's visible on pages `/admin` and `/admin/something`, but not at `/home`, `/home/admin` or `/`. +`path=/admin` 옵션을 사용하여 설정한 쿠키는 `/admin`과 `/admin/something`에선 볼 수 있지만, `/home`, `/home/admin`, `/`에선 볼 수 없습니다. -Usually, we should set `path` to the root: `path=/` to make the cookie accessible from all website pages. If this attribute is not set the default is calculated using [this method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#path_default_value). ->>>>>>> upstream/master +특별한 경우가 아니라면, `path` 옵션을 `path=/`같이 루트로 설정해 웹사이트의 모든 페이지에서 쿠키에 접근할 수 있도록 합시다. 이 속성을 설정하지 않으면 기본값은 [이 방식](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#path_default_value)에 따라 계산됩니다. ## expires와 max-age -<<<<<<< HEAD -expires(유효 일자)나 max-age(만료 기간) 옵션이 지정되어있지 않으면, 브라우저가 닫힐 때 쿠키도 함께 삭제됩니다. 이런 쿠키를 "세션 쿠키(session cookie)"라고 부릅니다. +`expires`나 `max-age` 옵션이 지정되어 있지 않으면, 브라우저나 탭이 닫힐 때 쿠키도 함께 삭제됩니다. 이런 쿠키를 "세션 쿠키"라고 부릅니다. -`expires` 나 `max-age` 옵션을 설정하면 브라우저를 닫아도 쿠키가 삭제되지 않습니다. +브라우저를 닫아도 쿠키가 살아남게 하려면 `expires`나 `max-age` 속성을 설정하면 됩니다. 둘 다 설정되어 있다면 `max-age`가 우선합니다. - **`expires=Tue, 19 Jan 2038 03:14:07 GMT`** 브라우저는 설정된 유효 일자까지 쿠키를 유지하다가, 해당 일자가 도달하면 쿠키를 자동으로 삭제합니다. -쿠키의 유효 일자는 반드시 GMT(Greenwich Mean Time) 포맷으로 설정해야 합니다. `date.toUTCString`을 사용하면 해당 포맷으로 쉽게 변경할 수 있습니다. 아래는 유효 기간이 하루인 쿠키를 만드는 예시입니다. -======= -By default, if a cookie doesn't have one of these attributes, it disappears when the browser/tab is closed. Such cookies are called "session cookies" - -To let cookies survive a browser close, we can set either the `expires` or `max-age` attribute. `max-Age` has precedence if both are set. - -- **`expires=Tue, 19 Jan 2038 03:14:07 GMT`** - -The cookie expiration date defines the time when the browser will automatically delete it (according to the browser's time zone). - -The date must be exactly in this format, in the GMT timezone. We can use `date.toUTCString` to get it. For instance, we can set the cookie to expire in 1 day: ->>>>>>> upstream/master +쿠키의 유효 일자는 반드시 GMT 포맷으로 설정해야 합니다. `date.toUTCString`을 사용하면 해당 포맷으로 쉽게 변경할 수 있습니다. 아래는 유효 기간이 하루인 쿠키를 만드는 예시입니다. ```js // 지금으로부터 하루 후 @@ -266,23 +157,14 @@ document.cookie = "user=John; expires=" + date; `expires` 옵션값을 과거로 지정하면 쿠키는 삭제됩니다. -- **`max-age=3600`** +- **`max-age=3600`** -<<<<<<< HEAD `max-age`는 `expires` 옵션의 대안으로, 쿠키 만료 기간을 설정할 수 있게 해줍니다. 현재부터 설정하고자 하는 만료일시까지의 시간을 초로 환산한 값을 설정합니다. 0이나 음수값을 설정하면 쿠키는 바로 삭제됩니다. ```js // 1시간 뒤에 쿠키가 삭제됩니다. -======= -It's an alternative to `expires` and specifies the cookie's expiration in seconds from the current moment. - -If set to zero or a negative value, the cookie is deleted: - -```js -// cookie will die in +1 hour from now ->>>>>>> upstream/master document.cookie = "user=John; max-age=3600"; // 만료 기간을 0으로 지정하여 쿠키를 바로 삭제함 @@ -295,155 +177,91 @@ document.cookie = "user=John; max-age=0"; 이 옵션을 설정하면 HTTPS로 통신하는 경우에만 쿠키가 전송됩니다. -**`secure` 옵션이 없으면 기본 설정이 적용되어 `http://site.com`에서 설정(생성)한 쿠키를 `https://site.com`에서 읽을 수 있고, `https://site.com`에서 설정(생성)한 쿠키도 `http://site.com`에서 읽을 수 있습니다.** +**`secure` 옵션이 없으면 기본 설정이 적용되어 `http://site.com`에서 설정한 쿠키를 `https://site.com`에서 읽을 수 있고, `https://site.com`에서 설정한 쿠키도 `http://site.com`에서 읽을 수 있습니다.** 쿠키는 기본적으로 도메인만 확인하지 프로토콜을 따지진 않기 때문입니다. -<<<<<<< HEAD 하지만 `secure` 옵션이 설정된 경우, `https://site.com`에서 설정한 쿠키는 `http://site.com`에서 접근할 수 없습니다. 쿠키에 민감한 내용이 저장되어 있어 암호화되지 않은 HTTP 연결을 통해 전달되는 걸 원치 않는다면 이 옵션을 사용하면 됩니다. ```js -// (https:// 로 통신하고 있다고 가정 중) +// https:// 로 통신하고 있다고 가정 중 // 설정한 쿠키는 HTTPS 통신시에만 접근할 수 있음 -======= -With this attribute, if a cookie is set by `https://site.com`, then it doesn't appear when the same site is accessed by HTTP, as `http://site.com`. So if a cookie has sensitive content that should never be sent over unencrypted HTTP, the `secure` flag is the right thing. - -```js -// assuming we're on https:// now -// set the cookie to be secure (only accessible over HTTPS) ->>>>>>> upstream/master document.cookie = "user=John; secure"; ``` ## samesite -<<<<<<< HEAD 또 다른 보안 속성인 `samesite` 옵션은 크로스 사이트 요청 위조(cross-site request forgery, XSRF) 공격을 막기 위해 만들어진 옵션입니다. -======= -This is another security attribute `samesite`. It's designed to protect from so-called XSRF (cross-site request forgery) attacks. ->>>>>>> upstream/master 아래 XSRF 공격 시나리오를 통해 이 속성의 동작 방식과 언제 이 속성을 유용하게 사용할 수 있는지 알아보도록 합시다. ### XSRF 공격 -<<<<<<< HEAD -현재 `bank.com`에 로그인되어있다고 가정해 봅시다. 해당 사이트에서 사용되는 인증 쿠키가 브라우저에 저장되고, 브라우저는 `bank.com`에 요청을 보낼 때마다 인증 쿠키를 함께 전송할 것입니다. 서버는 전송받은 쿠키를 이용해 사용자를 식별하고, 보안이 필요한 재정 거래를 처리합니다. -======= -Imagine, you are logged into the site `bank.com`. That is: you have an authentication cookie from that site. Your browser sends it to `bank.com` with every request so that it recognizes you and performs all sensitive financial operations. ->>>>>>> upstream/master +현재 `bank.com`에 로그인되어 있다고 가정해 봅시다. 해당 사이트에서 사용되는 인증 쿠키가 브라우저에 저장되고, 브라우저는 `bank.com`에 요청을 보낼 때마다 인증 쿠키를 함께 전송할 것입니다. 서버는 전송받은 쿠키를 이용해 사용자를 식별하고, 보안이 필요한 재정 거래를 처리합니다. -이제 (로그아웃하지 않고) 다른 창을 띄워서 웹 서핑을 하던 도중에 뜻하지 않게 `evil.com`에 접속했다 가정해 봅시다. 이 사이트엔 해커에게 송금을 요청하는 폼(form) `
`이 있고, 이 폼은 자동으로 제출되도록 설정되어 있습니다. +이제 로그아웃하지 않고 다른 창을 띄워서 웹 서핑을 하던 도중에 뜻하지 않게 `evil.com`에 접속했다 가정해 봅시다. 이 사이트엔 해커에게 송금을 요청하는 폼 ``이 있고, 이 폼은 자동으로 제출되도록 설정되어 있습니다. -<<<<<<< HEAD -폼이 `evil.com`에서 은행 사이트로 바로 전송될 때 인증 쿠키도 함께 전송됩니다. `bank.com`에 요청을 보낼 때마다 `bank.com`에서 설정한 쿠키가 전송되기 때문입니다. 은행은 전송받은 쿠키를 읽어 (해커가 아닌) 계정 주인이 접속한 것이라 생각하고 해커에게 돈을 송금합니다. +폼이 `evil.com`에서 은행 사이트로 바로 전송될 때 인증 쿠키도 함께 전송됩니다. `bank.com`에 요청을 보낼 때마다 `bank.com`에서 설정한 쿠키가 전송되기 때문입니다. 은행은 전송받은 쿠키를 읽어 해커가 아니라 계정 주인이 접속한 것이라 생각하고 해커에게 돈을 송금합니다. ![](cookie-xsrf.svg) 이런 공격을 크로스 사이트 요청 위조라고 부릅니다. -실제 은행은 당연히 이 공격을 막을 수 있도록 시스템을 설계합니다. `bank.com`에서 사용하는 모든 폼에 "XSRF 보호 토큰(protection token)"이라는 특수 필드를 넣어서 말이죠. 이 토큰은 악의적인 페이지에서 만들 수 없고, 원격 페이지에서도 훔쳐 올 수 없도록 구현되어 있습니다. 따라서 악의적인 페이지에서 폼을 전송하더라도 보호 토큰이 없거나 서버에 저장된 값과 일치하지 않기 때문에 요청이 무용지물이 됩니다. +실제 은행은 당연히 이 공격을 막을 수 있도록 시스템을 설계합니다. `bank.com`에서 사용하는 모든 폼에 "XSRF 보호 토큰"이라는 특수 필드를 넣어서 말이죠. 이 토큰은 악의적인 페이지에서 만들 수 없고, 원격 페이지에서도 훔쳐 올 수 없도록 구현되어 있습니다. 따라서 악의적인 페이지에서 폼을 전송하더라도 보호 토큰이 없거나 서버에 저장된 값과 일치하지 않기 때문에 요청이 무용지물이 됩니다. 하지만 이런 절차는 구현에 시간이 걸린다는 단점을 수반합니다. 모든 폼에 보호 토큰을 세팅해줘야 하죠. 또한 요청 전부를 검수해야 합니다. ### samesite 옵션 -쿠키의 `samesite` 옵션을 이용하면 "XSRF 보호 토큰" 없이도 (이론상으로) 크로스 사이트 요청 위조를 막을 수 있습니다. -======= -The browser sends cookies every time you visit the site `bank.com`, even if the form was submitted from `evil.com`. So the bank recognizes you and performs the payment. - -![](cookie-xsrf.svg) - -This is a so-called "Cross-Site Request Forgery" (in short, XSRF) attack. - -Real banks are protected from it of course. All forms generated by `bank.com` have a special field, a so-called "XSRF protection token", that an evil page can't generate or extract from a remote page. It can submit a form there, but can't get the data back. The site `bank.com` checks for such a token in every form it receives. - -Such a protection takes time to implement though. We need to ensure that every form has the required token field, and we must also check all requests. - -### Use cookie samesite attribute - -The cookie `samesite` attribute provides another way to protect from such attacks, that (in theory) should not require "xsrf protection tokens". ->>>>>>> upstream/master +쿠키의 `samesite` 옵션을 이용하면 이론상 "XSRF 보호 토큰" 없이도 크로스 사이트 요청 위조를 막을 수 있습니다. 이 옵션엔 두 가지 값을 설정할 수 있습니다. -<<<<<<< HEAD -- **`samesite=strict`(값을 설정하지 않고 그냥 `samesite` 옵션만 써줘도 동일하게 동작함)** -======= - **`samesite=strict`** ->>>>>>> upstream/master 사용자가 사이트 외부에서 요청을 보낼 때, `samesite=strict` 옵션이 있는 쿠키는 절대로 전송되지 않습니다. -<<<<<<< HEAD 메일에 있는 링크를 따라 접속하거나 `evil.com`과 같은 사이트에서 폼을 전송하는 경우 등과 같이 제3의 도메인에서 요청이 이뤄질 땐 쿠키가 전송되지 않죠. 인증 쿠키에 `samesite` 옵션이 있는 경우, XSRF 공격은 절대로 성공하지 못합니다. `evil.com`에서 전송하는 요청엔 쿠키가 없을 것이고, `bank.com`은 미인식 사용자에게 지급을 허용하지 않을 것이기 때문입니다. -이 보호장치는 꽤 믿을 만합니다. `bank.com`에서 수행하는 모든 작업은 samesite 쿠키를 함께 전송하기 때문이죠. -======= -In other words, whether a user follows a link from their email, submits a form from `evil.com`, or does any operation that originates from another domain, the cookie is not sent. - -If authentication cookies have the `samesite=strict` attribute, then an XSRF attack has no chance of succeeding, because a submission from `evil.com` comes without cookies. So `bank.com` will not recognize the user and will not proceed with the payment. - -The protection is quite reliable. Only operations that come from `bank.com` will send the `samesite=strict` cookie, e.g. a form submission from another page at `bank.com`. ->>>>>>> upstream/master +이 보호장치는 꽤 믿을 만합니다. `bank.com`에서 수행하는 모든 작업은 `samesite=strict` 쿠키를 함께 전송하기 때문이죠. 하지만 약간의 불편함도 감수해야 합니다. -<<<<<<< HEAD 만약 사용자가 메모장 등에 `bank.com`에 요청을 보낼 수 있는 링크를 기록해 놓았다가 이 링크를 클릭해 접속하면 `bank.com`이 사용자를 인식하지 못하는 상황이 발생하기 때문입니다. 실제로 이런 경우 `samesite=strict` 옵션이 설정된 쿠키는 전송되지 않습니다. -이런 문제는 쿠키 두 개를 함께 사용해 해결할 수 있습니다. "Hello, John"과 같은 환영 메시지를 출력해주는 "일반 인증(general recognition)"용 쿠키, 데이터 교환 시 사용하는 `samesite=strict` 옵션이 있는 쿠키를 따로 둬서 말이죠. 이렇게 하면 외부 사이트를 통해 접근한 사용자도 정상적으로 환영 메시지를 볼 수 있습니다. 지급은 무조건 은행의 사이트를 통해서만 수행되도록 만들면 됩니다. -======= -When a user follows a legitimate link to `bank.com`, like from their notes, they'll be surprised that `bank.com` does not recognize them. Indeed, `samesite=strict` cookies are not sent in that case. - -We could work around that by using two cookies: one for "general recognition", only to say: "Hello, John", and the other one for data-changing operations with `samesite=strict`. Then, a person coming from outside of the site will see a welcome, but payments must be initiated from the bank's website, for the second cookie to be sent. ->>>>>>> upstream/master +이런 문제는 쿠키 두 개를 함께 사용해 해결할 수 있습니다. "Hello, John"과 같은 환영 메시지를 출력해주는 "일반 인증"용 쿠키와 데이터 교환 시 사용하는 `samesite=strict` 옵션이 있는 쿠키를 따로 둬서 말이죠. 이렇게 하면 외부 사이트를 통해 접근한 사용자도 정상적으로 환영 메시지를 볼 수 있습니다. 결제는 무조건 은행의 사이트를 통해서만 수행되도록 만들면 됩니다. -- **`samesite=lax` (same as `samesite` without value)** +- **`samesite=lax` (값 없이 `samesite`만 쓴 경우와 동일합니다)** -<<<<<<< HEAD `samesite=lax`는 사용자 경험을 해치지 않으면서 XSRF 공격을 막을 수 있는 느슨한 접근법입니다. -======= -A more relaxed approach that also protects from XSRF and doesn't break the user experience. ->>>>>>> upstream/master `strict`와 마찬가지로 `lax`도 사이트 외부에서 요청을 보낼 때 브라우저가 쿠키를 보내는 걸 막아줍니다. 하지만 예외사항이 존재합니다. 아래 두 조건을 동시에 만족할 때는 `samesite=lax` 옵션을 설정한 쿠키가 전송됩니다. -1. "안전한" HTTP 메서드인 경우(예: GET 방식. POST 방식은 해당하지 않음). +1. "안전한" HTTP 메서드인 경우입니다. 예를 들어 GET 방식은 해당하지만, POST 방식은 해당하지 않습니다. -<<<<<<< HEAD - 안전한 HTTP 메서드 목록은 [RFC7231 명세](https://tools.ietf.org/html/rfc7231)에서 확인할 수 있습니다. 안전한 메서드는 읽기 작업만 수행하고 쓰기나 데이터 교환 작업은 수행하지 않습니다. 참고로, 링크를 따라가는 행위는 항상 GET 방식이기 때문에 안전한 메서드만 쓰입니다. - -2. 작업이 최상위 레벨 탐색에서 이루어질 때(브라우저 주소창에서 URL을 변경하는 경우). + 안전한 HTTP 메서드 목록은 [RFC7231 명세](https://tools.ietf.org/html/rfc7231)에서 확인할 수 있습니다. 안전한 메서드는 읽기 작업만 수행하고 쓰기나 데이터 교환 작업은 수행하지 않습니다. 참고로, 링크를 따라가는 행위는 항상 GET 방식이기 때문에 안전한 메서드만 쓰입니다. + +2. 작업이 최상위 레벨 탐색에서 이루어질 때입니다. 브라우저 주소창에서 URL을 변경하는 경우가 여기에 해당합니다. 대다수의 작업은 이 조건을 충족합니다. 하지만 `