Frontend
브라우저 싸움에 등 터지는 개발자들을 위한 HTTP쿠키와 톰캣 쿠키 프로세서 이야기
2019년 11월 14일
원문에서 보기 ↗무심코 프로젝트의 라이브러리를 버전 업하다가 예상치 못한 에러가 발생한 경험이 다들 있을 것입니다. 주로 이런 에러는 성가신 호환성 문제이거나 버전 별 버그가 원인이지만, 가끔은 버전과 세월을 따라 발전하는 기술 표준이 원인일 때도 있습니다. 변화하는 기술에 대한 정확한 지식이 없으면 애용하던 라이브러리 버전이 deprecate 될 때 어려움을 겪을 수밖에 없는데요, 이번 글에서는 회원개발팀에서 일어난 쿠키 버그와, 그 원인이 된 현재 진행형 HTTP 쿠키 스펙 변화에 대해 소개해 드리려고 합니다.
문제의 발단
패딩 문자 인식 문제와 따옴표가 사라지는 문제 발견
회원개발팀에서 관리하는 회원 인증 플랫폼은 상당히 오래된 시스템입니다. 회원 인증 플랫폼은 회원 관리 시스템을 전담 개발하여 NHN의 다른 서비스들에서 손쉽게 회원관리 기능을 사용할 수 있기 위해 만들어졌습니다. 회원 인증 플랫폼은 신스펙 RFC6265이 발표되기 전에 개발되었기 때문에 레거시 쿠키 표준을 사용하고 있었고, 회사의 다른 시스템들도 그랬기 때문에 문제없이 10년이 넘는 세월을 버텨 왔습니다. 하지만 새로운 프로젝트들이 최신 버전의 컨테이너를 사용하면서 문제가 생겼습니다.
회원 인증 플랫폼에서는 회원의 로그인 정보를 저장할 때 Base64인코딩된 정보를 생성하고 패딩으로 “=” 문자를 사용해 쿠키를 만들어 왔습니다. 하지만 어느 순간부터 회원 인증 플랫폼을 사용하는 특정 서버를 지나면 =가 없어지거나 쿠키를 감싸는 따옴표가 사라지며 확률적으로 로그인이 풀려버리는 문제가 발생하기 시작했습니다.
처음에는 스프링 부트의 내장 톰캣 문제가 아닌가, 특정 톰캣에 버그가 있는 것이 아닌가의 추측을 했습니다. 긴 세월 동안 잘 작동하며 안정성을 증명한 시스템 자체에 문제가 있을 것이라고는 생각을 하기 어려웠기 때문일 것입니다. 회원개발팀에서 원인을 추적하기 위해 톰캣 소스 분석과 버전별 실험을 통해 확인해본 결과, 저희가 생각한 것보다 훨씬 흥미로운 원인을 찾게 되었습니다. 이해를 돕기 위해 HTTP 쿠키의 역사부터 설명을 시작합니다.
HTTP 쿠키의 역사

넷스케이프 0.9와 초기 쿠키의 등장
넷스케이프 브라우저 0.9 버전부터 등장한 HTTP 쿠키는 웹 프로그래밍에서 빼놓을 수 없는 개념이며 동시에 가장 오래된 기술이기도 합니다. 표준이 제시되기 전에 널리 상용화된 기술들이 그러듯이 초기의 HTTP 쿠키는 넷스케이프가 제시한 쿠키 표준에 따라 개발되었습니다. 하지만 안타깝게도 넷스케이프 개발자들이 제시한 쿠키 표준 문서는 굉장히 애매모호하게 작성되어 있었고, 개발자 각각의 주관이 포함된 쿠키 구현들로 인해 큰 호환성 문제가 대두되었습니다.
RFC2109 등장과 쿠키 스펙 제한
이 문제를 해결하고 새로운 표준을 제시하기 위해 나타난 문건이 RFC2109였습니다. RFC2109는 넷스케이프의 스펙에서 많은 특수문자를 제외시켰고, RFC2616 토큰을 이용해야 한다는 제안을 했습니다. 또, 특수문자에 대해 따옴표와 escaping을 강제했습니다. 강력한 스펙 제안을 두어 중구난방이었던 HTTP 쿠키를 하나의 방식으로 정리하고자 한 것입니다. 하지만 혼란을 바로잡으려는 벨 연구소의 희망과는 달리 개발자들은 이 스펙을 현실과 너무 동떨어져 있다고 여겨 거의 구현하지 않았습니다.
RFC2965의 Set-cookie2 제시
다시 쿠키에 정형화된 표준을 제시하려고 나타난 표준은 2000년의 RFC2965였습니다. RFC2965는 난장판이 이미 되어버린 Set-cookie 스펙을 포기하고 RFC2109에 기능들을 더 추가해서 새로운 Set-cookie2 스펙을 제시했습니다. 호환성을 가지기 위해 Set-cookie와 분리된 새 표준을 제시하며 점진적인 규격화를 도모한 것입니다. 하지만 업계의 반응은 싸늘했고, 이 스펙을 난센스라고 생각한 개발자들은 RFC2965 또한 무시했습니다.
RFC6265와 표준 스펙 문서화
기나긴 우여곡절 끝에 HTML5 시대가 도래했고, 새로운 스펙을 강제하는 것을 포기한 RFC6265가 2011년에 발표되었습니다. RFC6265는 이전 시도들과는 달리 새로운 기능을 제시하기보다는 상용화되어있던 브라우저와 웹 서버들의 관행을 문서화하는 데에 집중했습니다. 새로운 시스템들이 현 웹 환경에 맞게 개발될 수 있도록 가이드를 한 것입니다. RFC6265는 현실과 가장 부합하는 HTTP 표준으로 생각되고 있으며 현재 많은 애플리케이션들과 브라우저들이 RFC6265를 받아들이고 있는 상태입니다.
현재는 아직도 넷스케이프가 제시한 V0의 쿠키들이 굉장히 많이 사용되고 있지만, 점점 기술 표준은 RFC6265를 향해 변화해 가고 있습니다. 많은 개발자들의 애플리케이션을 지탱하고 있는 톰캣과 같은 소프트웨어가 RFC6265를 점차 기본값으로 채택함에 따라 레거시 스펙의 HTTP 쿠키와 RFC6265 스펙의 쿠키의 차이점에 대해 아는 것이 미래에 큰 도움이 될 것이라 생각합니다.
톰캣과 HTTP 쿠키 프로세서
위에서 알아봤던 HTTP 쿠키의 역사에서 알 수 있듯이 HTTP 쿠키의 스펙은 긴 시간 동안 엄청난 혼란과 무표준 상태를 겪었습니다. 그렇기 때문에 톰캣 8은 범용성을 보장하기 위해 두 가지 쿠키 프로세서인 LegacyCookieProcessor와 Rfc6265 CookieProcessor를 모두 내장하고 있습니다. 뿐만 아니라, 이 쿠키 프로세서를 커스터마이징 할 수 있는 여러 가지 옵션을 제공하고 있습니다. 표준이 애매모호한 쿠키 스펙에 대처하기 위해 개발자가 알맞은 쿠키 버전을 택하고 여러 가지 정책을 커스터마이징 해서 개발한 시스템에 제일 적합한 프로세싱을 할 수 있습니다.
별다른 세팅을 하지 않으면 톰캣 8은 기본값으로 LegacyCookieProcessor를 사용하도록 되어 있었으나, 톰캣 8.5를 기점으로 Rfc6265 CookieProcessor를 기본값으로 사용하도록 변경이 되었습니다. 이 때문에 Rfc6265 쿠키 스펙을 확실하게 인지하지 않는다면 신규 버전의 톰캣으로 업그레이드하거나, 회원 인증 플랫폼과 같이 사용 서버의 스펙을 알지 못할 때 예키치 못한 오류가 발생할 확률이 있습니다.
레거시 쿠키 vs RFC6265 쿠키
"레거시 쿠키"는 V0, V1, 여러 구 RFC문서에 근거하는 다양한 스펙을 가질 수 있기 때문에 레거시 쿠키는 톰캣의 Legacy cookie processor 가 인용한 스펙을 기준으로 다루겠습니다. 실제로 Legacy cookie processor는 혼란스러운 표준 문제 때문에 RFC2109, 2616, 6265를 모두 부분 부분 인용하고 있습니다.
간단 요약
| 쿠키 | 버전 속성 | Set-cookie 헤더 | 만료 메커니즘 | 도메인 속성 | 쿠키 name,value 제한사항 | 쿠키값 |
|---|---|---|---|---|---|---|
| 레거시 | Version=0, 1 | Set-cookie, Set-cookie2 | max-age, expires 혼용 | .으로 시작 | name,value 모두 HTTP/1.1 token형식 | name=이후의 token형식 value 또는 "로 감싸진 값 |
| RFC6265 | 사용하지 않음 | Set-cookie | max-age가 있을 경우 expires 무시 | .으로 시작하지 않음 | name만 HTTP/1.1 token 형식 | 첫 =와 첫 ;사이의 문자 |
쿠키 버전
- 레거시 쿠키: Version 헤더를 사용해서 cookie-version을 명시하며 넷스케이프 스펙의 쿠키는 Version=0을 사용하거나 버전 헤더를 사용하지 않고, RFC2965 쿠키는 Version=1을 사용합니다. 톰캣의 LegacyCookieProcessor는 버전 0의 쿠키를 만드는 것을 시도하고, 특별히 버전 1의 스펙을 인용할 때만 버전 1로 쿠키를 생성합니다.
- RFC6265 쿠키: 새로운 스펙을 제시하기보다 현업 스펙을 정리하는 것을 목표로 했기 때문에 $Version을 사용하지 않습니다.
Set-cookie 헤더
- 레거시 쿠키: Set-cookie를 통해 일반 쿠키 프로세싱을 하고, Set-cookie2 스펙을 통해 RFC2965 전용 스펙을 사용하지만, 톰캣의 LegacyCookieProcessor는 Set-cookie2를 사용하고 있지 않습니다.
- RFC6265 쿠키: Set-cookie만을 사용하고 있습니다.
쿠키 만료 메커니즘
- 레거시 쿠키: RFC2965는 Expires 속성을 허용하고 있지 않으며, HTTP/1.1 스펙으로 계산한 max-age만을 허용하고 있습니다. 하지만 IE6,7 브라우저는 max-age를 구현하지 않았기 때문에 톰캣의 LegacyCookieProcessor는 max-age와 동일한 expires를 계산해서 둘 다 추가하고 있습니다. 즉시 만료는 max-age=0을 사용합니다.
- RFC6265 쿠키: 동일한 쿠키에도 expires와 max-age를 둘 다 사용 가능하지만, max-age가 있는 경우 expires를 완전 무시하도록 되어 있습니다. 즉시 만료는 과거의 시간을 expires 어트리뷰트에 사용합니다.
도메인 속성
- Legacy cookie 스펙의 브라우저: V0의 스펙은 도메인 문법에 대해 자세히 기술하고 있지 않습니다. RFC2965의 V1스펙에서는 도메인명은
.으로 시작한다고 명시하고 있으며,abc.com은 자동으로.abc.com으로 전환하여 저장하도록 되어 있습니다. - RFC6265 쿠키: 레거시 쿠키와 정면으로 반대되는 스펙으로, 도메인명의 첫 글자가
.인 것을 혀용 하지 않습니다. 스펙에는 위배되지만 첫.을 확인하면 해당 문자를 무시해서 프로세싱합니다.
RFC6265 스펙에 정의된 것과는 다르게, 톰캣의 Rfc6265CookieProcessor는 8.5.x 버전부터 첫 .을 무시하지 않고 예외가 발생하게 됩니다.
| 상황 | LegacyCookieProcessor | 8.0.x Rfc6265CookieProcessor | 8.5.x Rfc6265CookieProcessor |
|---|---|---|---|
도메인을 .으로 시작 | 그대로 처리 | .이 제거됨 | Exception 발생 |
도메인을 .으로 시작하지 않음 | .이 추가됨 | 그대로 처리 | 그대로 처리 |
쿠키값 요구사항과 처리
가장 차이가 많고 복잡한 부분으로, 버전마다 굉장히 다른 스펙을 제시하고 있습니다
Netscape V0
Netscape
NAME=VALUE
This string is a sequence of characters excluding semi-colon, comma and white space. If there is a need to place such data in the name or value, some encoding method such as URL style %XX encoding is recommended, though no encoding is defined or required.
This is the only required attribute on the Set-Cookie header.
NAME=VALUE 스트링은 ;, ,, <공백>을 제외한 문자로 하며, 인코딩을 권장한다는 굉장히 애매모호한 요구사항 밖에 제시하고 있지 않습니다. 하지만 많은 브라우저들은 여기에 추가로 다음 요구사항을 추가 구현했습니다
- NAME 또는 VALUE는 empty string이 될 수 있다
- NAME=VALUE스트링에
=가 없다면, NAME은 Empty string이 되고 나머지 값을 VALUE로 처리한다. Set-Cookie: =abc와 같이 NAME이 없는 쿠키는Set-Cookie: abc로 출력한다- 넷스케이프의 요구사항과 다르게
,와<공백>을 허용하지만, 값의 앞뒤에 있는 공백은 strip 한다. - 컨트롤 문자인 00, 1F, 7F을 허용하지 않는다.
- 유니코드 문자열에 대한 처리는 각각 브라우저가 마음대로 구현해서 혼돈의 스펙 차이가 있습니다
- 오페라와 구글 크롬은 UTF-8로 인코딩합니다
- IE는 기본값 인코딩을 사용하지만 UTF-8은 절대 사용하지 않습니다
- 파이어폭스는 UTF-16의 로우 바이트만을 사용합니다 (ISO-8859-1이 아니면 값이 깨짐)
- 사파리는 ASCII 문자를 제외하고는 전송을 거부합니다.
RFC2965 V1
쿠키의 name은 HTTP/1.1 스펙의 토큰 형식을 요구하며, value는 HTTP/1.1 토큰 형식 또는 quoted-string을 요구하고 있습니다.
토큰에 대한 HTTP/1.1 스펙은 다음과 같습니다.
token = 1*<any CHAR except CTLs or separators>
separators = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | "\" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
그러므로, separators에 해당하는 문자를 사용하려면 DQUOTE로 감싼 quoted string으로 사용하는 것 만을 허용하고 있습니다.
RFC6265 cookie
쿠키의 name은 RFC2965와 같이 토큰 형식을 요구합니다. 하지만 cookie-value에 대해 차이가 있습니다.
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
; US-ASCII characters excluding CTLs,
; whitespace DQUOTE, comma, semicolon,
; and backslash
RFC6265에서는 cookie-value에 DQUOTE로 감싼 값이나 감싸지 않은 값 모두를 허용하며, 일괄적으로 컨트롤, 공백, ", ,, ;, \ 에 대한 제한을 두고 있습니다.
또한, 쿠키의 파싱에 대해 명확한 알고리즘을 제시하고 있습니다:
- set-cookie-string 이
;를 포함할 경우, name-value-pair는 첫;이전까지의 값으로 이루어져 있다. - set-cookie-string 이
;를 포함하지 않는 경우, name-value-pair는 set-cookie-string전체이다 - name-value-pair에
=가 없을 경우 set-cookie-string 전체를 무시한다. - 쿠키의 name은 name-value-pair의
첫 =까지이고value는첫 = 이후이다. - name, value는 양옆 공백을 제거한다
- name이 empty string이라면 set-cookie-string 전체를 무시한다.
톰캣 버전별 차이
| 항목 | Tomcat Legacy cookie processor | Tomcat 8.0.x Rfc6265 cookie processor | Tomcat 8.5.x Rfc6265 cookie processor |
|---|---|---|---|
cookie-value : cookie-value에 특수문자가 있으면 자동으로 "로 감싸는가? | O | X | X |
cookie-value : " 로 감싸지지 않은 cookie-value에 특수문자가 있으면 인식이 가능한가? | X (첫 HTTP/1.1 토큰의 separator 이후 값 사라짐) | O | O |
domain : domain이 .으로 시작해도 처리가 가능한가? | O (스펙 표준이다) | O (스펙은 아니지만 무시하고 처리) | X (에러) |
주의해야 하는 브라우저 특성
IE, Microsoft Edge
- Max-age 속성을 구현하지 않았다.
- Max-age 속성과 동일한 시간으로 계산된 Expires속성을 세팅해서 전송해야 한다.
- Rfc6265 CookieProcessor는 동일한 시간의 Max-age와 Expires를 모두 추가한다.
- LegacyCookieProcessor는 V0쿠키와 always add expires 설정을 활성화한 상태에 대해 Expires를 추가한다 (V1쿠키를 사용하려면 always add expires를 활성화할 것을 권장)
- Rfc6265CookieProcessor에서 해당 문제에 대한 보정:
// RFC 6265 prefers Max-Age to Expires but... (see below)
int maxAge = cookie.getMaxAge();
if (maxAge > -1) {
// Negative Max-Age is equivalent to no Max-Age
header.append("; Max-Age=");
header.append(maxAge);
// Microsoft IE and Microsoft Edge don't understand Max-Age so send
// expires as well. Without this, persistent cookies fail with those
// browsers. See http://tomcat.markmail.org/thread/g6sipbofsjossacn
// Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
header.append ("; Expires=");
// To expire immediately we need to set the time in past
if (maxAge == 0) {
header.append(ANCIENT_DATE);
} else {
COOKIE_DATE_FORMAT.get().format(
new Date(System.currentTimeMillis() + maxAge * 1000L),
header,
new FieldPosition(0));
}
}
- LegacyCookieProcessor에서의 보정:
// Max-Age=secs ... or use old "Expires" format
int maxAge = cookie.getMaxAge();
if (maxAge >= 0) {
if (version > 0) {
buf.append ("; Max-Age=");
buf.append (maxAge);
}
// IE6, IE7 and possibly other browsers don't understand Max-Age.
// They do understand Expires, even with V1 cookies!
if (version == 0 || getAlwaysAddExpires()) {
// Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
buf.append ("; Expires=");
// To expire immediately we need to set the time in past
if (maxAge == 0) {
buf.append( ANCIENT_DATE );
} else {
COOKIE_DATE_FORMAT.get().format(
new Date(System.currentTimeMillis() + maxAge * 1000L),
buf,
new FieldPosition(0));
}
}
}
- Rfc6265CookieProcessor로 변경 시 Max-age와 Expires가 이중으로 추가되는 Set-Cookie필드:
Set-Cookie: TOAST_ID_NEO_CHK=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Domain=toast.com; Path=/
Set-Cookie: TOAST_ID_NEO_SES=AAAA....; Domain=toast.com; Path=/
Set-Cookie: TOAST_ID_LAST_ID=; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Domain=toast.com; Path=/
Google chrome
- Cookie Domain
- 앞에
.이 포함되는 경우(Legacy 스펙으로 처리)- Set-Cookie에 domain을 지정한 경우 Header의 Set-Cookie의 Domain 앞에
.의 존재 여부 상관없이.을 포함시킨다.- Chrome Test 1 참조
- Set-Cookie에 domain을 지정한 경우 Header의 Set-Cookie의 Domain 앞에
- 앞에
.이 포함되지 않는 경우(RFC6265 스펙으로 처리)- Set-Cookie에 domain을 지정하지 않은 경우
.을 포함시키지 않는다.- Chrome Test 2 참조
- Set-Cookie에 domain을 지정하지 않은 경우
- 앞에
Chrome Test
- test환경
- version : 버전 77.0.3865.90(공식 빌드) (64비트)
- date : 2019.10.01
Chrome Test 1
| domain 설정 | Response Header | Chrome Cookie |
|---|---|---|
| sub domain제외 | Set-Cookie: test-cookie=cookie-value===boot; Domain=testcookie.com; Path=/ | * domain : .testcookie.com * name : test-cookie * value : cookie-value===boot |
| sub domain포함 | Set-Cookie: test-cookie=cookie-value===boot; Domain=local.testcookie.com; Path=/ | * domain : .local.testcookie.com * name : test-cookie * value : cookie-value===boot |
Chrome Test 2
| domain 설정 | Response Header | Chrome Cookie |
|---|---|---|
| domain 설정 없음 | * Set-Cookie: test-cookie=cookie-value===boot; Path=/ | * domain : local.testcookie.com * name : test-cookie * value : cookie-value===boot |
쿠키 프로세서 혼용에서 발생하는 문제
위와 같은 차이점 때문에 쿠키 프로세서를 혼용하게 되면 예상치 못한 문제가 발생할 수 있습니다. 일반적인 프로젝트에서는 일괄적으로 톰캣 버전 관리와 설정을 하기 때문에 문제가 되지 않지만, 회원 인증 플랫폼의 인증 모듈 등의 쿠키를 사용하는 dependency는 충분히 아래와 같은 상황이 일어날 수 있습니다.
쿠키 특수문자 파싱 에러

- LegacyCookieProcessor를 사용하는 서버에서 session="hexstring=="과 같이 특수문자를 포함하는 쿠키를 만들어 냅니다. LegacyCookieProcessor는 RFC2965에 따라
Set-Cookie: session="hexstring=="의 요청을 하게 됩니다. 이는,=가 포함된 문자열은 HTTP/1.1의 토큰 형식이 아니기 때문에 Quoted string타입의 데이터로 쿠키를 표현하기 위함입니다. - 해당 쿠키를 보유한 UserAgent가 Rfc6265CookieProcessor를 사용하는 서비스로 접속합니다.
Set-Cookie: session="hexstring=="는 RFC6265와 호환되는 값이므로 정상적으로 처리를 하게 됩니다. 하지만 Rfc6265CookieProcessor의 서버에서 읽은 값 그대로 Set-Cookie를 요청한다고 가정합니다.- Rfc6265CookieProcessor에서 session="hexstring=="의 cookie value로 요청을 하게 되면
Set-Cookie: session=hexstring==과 같이 따옴표가 없는 방식으로 Set-Cookie를 요청하게 됩니다. RFC6265에서 쿠키의 값은 첫=이후의 값으로 정의하고 있기 때문에 따옴표를 붙이지 않아도 해석의 어려움이 없기 때문입니다. - UserAgent가 다시 LegacyCookieProcessor를 사용하는 서비스로 쿠키(
session=hexstring==)로 접속하면, legacyCookieProcessor는 따옴표가 없는 HTTP/1.1 토큰에서=라는 허용되지 않은 문자를 무시하고 쿠키(session=hexstring)로 인식합니다. 실제 톰캣 LegacyCookieProcessor에서는 해당 상황에서session=hexstring으로 첫 특수문자와 이후의 값을 모두 버려 버리기 때문입니다. - 해당 유저는 세션 쿠키가 손상되었기 때문에 오류를 발생시키고 로그인이 풀려 버립니다.
해결책
RFC6265 cookie processor 지향
조건
- tomcat 버전 통일
- 8.0.x이상 버전으로 통일 후 8.0.x에서는 RFC6265 cookie processor를 설정해 줍니다.
- tomcat 버전 통일 불가능한 경우
- tomcat 버전으로 인해서 RFC6265 cookie processor로 통일이 불가능하다면, Url Safe Base64와 같이 RFC6265 cookie processor와 Legacy cookie processor에서 모두 사용 가능한 token을 생성해서 사용해야 합니다.
불가능한 경우
- domain
- 톰캣 8.5를 기준으로 도메인 처리 메커니즘이 다르기 때문에 브라우저에서 cookie를 구울 때 domain을 어떻게 처리하는지 또한 권한 문제를 어떻게 처리하는지 꼭 확인해 봐야 합니다.
- cookie value
- 이미 서비스 중이며 cookie에 HTTP/1.1 토큰의 separator가 들어간 경우 기존 token이 비정상적으로 동작할 수 있습니다.
Legacy cookie processor 지향
조건
- 현재 나온 tomcat버전들은 모두 Legacy cookie processor를 지원하기 때문에 모든 경우 가능합니다.
- tomcat 8.5.x이상은 LegacyCookieProcessor로 설정해야 합니다.
장점
- 일괄적으로 쿠키 프로세서를 통일하기 쉽습니다.
단점
- 스펙 하향평준화를 한다는 점이 마음에 걸릴 수밖에 없는 것은 단점입니다.
근본적인 해결책
- 어떤 쿠키 프로세서든 HTTP/1.1 스펙 토큰의 형식을 준수하여 LegacyCookieProcessor에서도 따옴표 없이 인식을 할 수 있게 합니다.
- 특수문자를 가능하면 사용하지 않습니다.
- 특수문자가 포함된다면 URL safe 인코딩을 합니다.
회원개발팀에서 회원 인증 플랫폼 쿠키에 대한 해결책
오래된 브라우저를 사용하는 서비스를 지원해야 하는 회원 인증 플랫폼의 특성상 일괄적으로 Rfc6265CookieProcessor로의 업그레이드는 불가능합니다. 또, 쿠키의 형식과 생성 로직을 바꾸게 되면 많은 유저가 로그인되어있는 모든 서비스에 직접적인 영향이 가므로 쿠키의 형식을 변경하는 것은 어렵습니다. 그러므로 저희 팀은 가장 합당한 해결책이 다음과 같다는 결론을 내렸습니다.
- 톰캣 8.5+ 를 사용하는 다른 프로젝트들에 LegacyCookieProcessor를 사용하도록 가이드하고, ALLOW_EQUALS_IN_VALUE 옵션을 true로 세팅하도록 가이드를 하는 방법을 택했습니다.
- 점진적으로 도입되는 신버전 회원 인증 플랫폼은 backward호환성과 미래에 주류가 될 Rfc6265 프로세서에 대한 대비를 하기 위해 url safe encoding을 확인했습니다.
Reference
- 초기 넷스케이프 쿠키 스펙 (https://curl.haxx.se/rfc/cookie_spec.html) - archive 복사본
- RFC2109 "HTTP State Management Mechanism" (https://www.ietf.org/rfc/rfc2109.txt)
- RFC2965 "HTTP State Management Mechanism" (https://www.ietf.org/rfc/rfc2965.txt)
- RFC6265 "HTTP State Management Mechanism" (https://www.ietf.org/rfc/rfc6265.txt)
- RFC2616 "Hypertext Transfer Protocol -- HTTP/1.1" (https://www.ietf.org/rfc/rfc2616.txt)
- MDN HTTP cookies (https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
- Stack overflow 토론 (https://stackoverflow.com/questions/1969232/allowed-characters-in-cookies)
Set-Cookie: test-cookie=cookie-value===boot; Domain=
* domain :
Set-Cookie: test-cookie=cookie-value===boot; Domain=
* domain :
* Set-Cookie: test-cookie=cookie-value===boot; Path=/
* domain :