『 Cookie 제대로 알고 사용하자 』
Cookie 는 아주 보편적이고 유명(?)하기 까지 하다.
웹 개발자는 물론이고 일반 웹 유저들 마저 쿠키에 대해 어느 정도는 알고 있다.
비 연결 지향인 웹 환경에서 사용자(일반적으로 웹 브라우저가 되겠다)와 웹 서버간의 특정 데이터의 상태 정보 저장을 위해 사용하는 하나의 기법이다.
이번 아티클은 이렇게 보편적인 쿠키를 개발단에서 사용할 때 참고할 만한 내용들을 정리해 본다.
1. 쿠키는 어디에 저장되는가?
일반적으로 쿠키는 아래의 경로에 TXT 파일 형태로 저장이 된다.
‘C:\Documents and Settings\현재로그인한 사용자\Cookies’
그러나 서버에서 쿠키의 만료 일자를 지정하지 않았다면 파일로 저장되지 않고 사용자 세션정보의 일부로써 유지된다.
즉 브라우저 기반 쿠키로써 브라우저를 닫으면 쿠키 역시 소멸되는 것이다
쿠키를 파일로 저장하지 않는 것은 보안상 이슈로 더 좋은 선택이 될 수 있다.
결론적으로, 쿠키를 설정할 때 만료일자의 지정 유/무에 따라 파일기반 쿠키 또는 세션(브라우저)기반 쿠키로 저장되는 것이다
참고> 만일 파일기반 쿠키의 경우 동일한 이름의 쿠키를 저장할 경우 이전 쿠키파일을 덮어 쓰게 된다
2. 쿠키의 제한 사항
웹 서버가 클라이언트에게 쿠키를 저장 할 경우 대부분 아래와 같은 제약 사항을 가진다.
1) 하나의 사이트에서 클라이언트에게 저장할 수 있는 최대 쿠키는 20개까지 이다.
2) 최대 4096 byte 쿠키 지원
쿠키의 수적 제한과 최대 크기의 제한 사항은 하위키 형태의 쿠키로 해결 할 수 있다.
즉, 만일 한 사이트에서 20개 이상의 쿠키가 필요하다면 하위 키를 포함한 쿠키를 사용하면 더 많은 쿠키를 저장하는 효과를 볼 수 있다.
Cookie[“Key”][“하위키1”]; Cookie[“Key”][“하위키2”];
이에 대한 MSDN 내용은 다음과 같다.
하위 키를 포함하는 쿠키를 사용하면 쿠키 파일의 크기를 제한하는 데에도 도움이 됩니다. 일반적으로 쿠키는 4096바이트로 제한되고 각 사이트마다 최대 20개의 쿠키를 저장할 수 있습니다. 하위 키를 포함하는 단일 쿠키를 사용하면 사이트에 할당된 20개의 쿠키보다 적은 수의 쿠키를 사용하게 됩니다. 또한 단일 쿠키에는 오버헤드(만료 정보 등)에 대한 50개 정도의 문자와 쿠키에 저장되는 값의 길이가 포함됩니다. 이 값은 모두 4096바이트 제한에 거의 근접한 값입니다. 5개의 쿠키를 개별적으로 저장하는 대신 하위 키 5개를 저장하면 개별 쿠키로 인한 오버헤드를 줄여 약 200바이트를 절약할 수 있습니다. |
3. 쿠키 샘플
이제 ASP.NET 에서 쿠키를 저장하고 불러오는 샘플 코드를 보자.
1) 쿠키 저장하기
아래 샘플 코드는 하위키를 가진 쿠키를 저장하는 두 가지 방법을 나타낸다
Response.Cookies["MyCookie"]["Cookie1"] = "값1"; Response.Cookies["MyCookie "][" Cookie2"] = “값2”; Response.Cookies["MyCookie "].Expires = DateTime.Now.AddDays(1); HttpCookie aCookie = new HttpCookie("MyCookie "); aCookie.Values["Cookie1"] = " 값1"; aCookie.Values["Cookie2"] = “값2” aCookie.Expires = DateTime.Now.AddDays(1); Response.Cookies.Add(aCookie); |
2) 쿠키 불러오기
아래 샘플 코드는 하위키를 가진 쿠키를 불러오는 방법을 나타낸다
샘플 처럼 해당 쿠키가 존재하는지 여부를 체크 하는 것이 좋다.(그렇지 않으면 ‘NullReferenceException’ 이 발생할 수 있다)
if(Request.Cookies["MyCookie "] != null) { Label1.Text = Server.HtmlEncode(Request.Cookies["MyCookie "][" Cookie1"]); Label2.Text = Server.HtmlEncode(Request.Cookies["MyCookie "][" Cookie2"]); } |
MSDN : 쿠키 값을 표시하기 전에 HtmlEncode 메서드를 호출하여 쿠키 내용을 인코딩했습니다. 이렇게 하면 악의적인 사용자가 실행 스크립트를 쿠키에 추가할 수 없습니다.
3) 모든 쿠키 읽기
현재 나의 사이트에서 저장한 모든 쿠키를 알아 볼 수 있는 샘플 코드이다. (MSDN)
for(int i=0; i<Request.Cookies.Count; i++) { aCookie = Request.Cookies[i]; output.Append("Name = " + aCookie.Name + "<br />"); if(aCookie.HasKeys) { for(int j=0; j<aCookie.Values.Count; j++) { subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys[j]); subkeyValue = Server.HtmlEncode(aCookie.Values[j]); output.Append("Subkey name = " + subkeyName + "<br />"); output.Append("Subkey value = " + subkeyValue + "<br /><br />"); } } else { output.Append("Value = " + Server.HtmlEncode(aCookie.Value) + "<br /><br />"); } } Label1.Text = output.ToString(); |
4. 쿠키 (유효) 범위 제어
쿠키를 저장 하고 난 후 사용할 때 (불러올 때) 에 유요한 범위를 아래와 같이 두 가지 방법으로 제어 할 수 있다.
1) 디렉터리 단위 제어
웹 서버의 특정 디렉터리(폴더)를 기준으로 쿠키의 범위를 제어 할 수 있다.
ASP.NET 의 HttpCookie 에는 Path 속성이 이와 관련된 속성이다.
만일 Path = “/Directory1” 로 설정된 쿠키라면 웹 서버의 ‘/Directory1’ 의 하위 폴더 및 가상 디렉터리에서만 쿠키 값을 읽어 들일 수 있게 되는 것이다.
이외의 폴더 및 루트에 속한 페이지에서는 쿠키를 사용할 수 없다.
Path 속성이 설정되지 않으면 기본적으로 웹 루트인 ‘/’ 가 설정되므로 해당 웹 사이트에서는 모두 사용 가능하게 되는 것이다.
참고> 일부 브라우저 에서는 경로의 대/소문자를 구분한다. 즉 URL 과 Path 속성이 정확히 대/소문자가 일치해야 쿠키를 사용할 수 있다.
2) 도메인 단위 제어
도메인 단위로도 범위 설정이 가능하다.
만일 특정 하위 도메인 에서만 사용가능한 쿠키를 만들고 싶으면 Domain 속성을 지정해 주면 된다.
Mkexp.pe.kr 사이트의 하위 도메인인 sub.mkex.pe.kr 에서만 쿠키를 사용하고 싶으면 Domain = “sub.mkex.pe.kr” 로 설정하면 된다.
또한 mkex.pe.kr 의 모든 하위도메인에서 사용가능 한 쿠키를 만들고 싶으면 Domain = “mkex.pe.kr” 로 설정하면 된다
5. 쿠키 허용 유/무
클라이언트는 서버에서 제공하는 쿠키를 허용할 지 결정 할 수있다.
아래 그림은 IE 6.0 에서 쿠키를 차단하는 모습니다.
이렇게 되면 웹 서버에서 쿠키를 사용하고 싶어도 할 수 없다.
단, 웹 서버에 쿠키 저장 시 오류는 발생하지 않는다. 다만 클라이언트는 쿠키를 저장하지 않으며 서버 요청 시 쿠키 값도 전달하지 않는 것이다.
따라서 쿠키 의존도가 상당히 강한 사이트의 경우 클라이언트의 쿠키 허용 유/무를 판단할 필요가 있다.
그러나 클라이언트의 브라우저가 쿠키를 허용 했는지 안 했는지 한방에 체크 할 수는 없다.
Msdn : Cookies 속성은 쿠키 사용 여부를 나타내지 않습니다. 대신 현재 브라우저에서 기본적으로 쿠키를 지원하는지 여부만 나타냅니다.
따라서 msdn 에서 이를 체크 하기 위해 조금은 무식한(?) 방법을 사용한다.
시나리오는 이렇다.
쿠키를 클라이언트에 저장해 한 후 다시 읽어 들여서 읽히면 쿠키가 허용된 것이고 아니면 쿠키가 불허용 된 것이라 판단하는 것이다.
아래는 msdn 의 샘플 코드이다.
//첫 번째 페이지(쿠키를 작성하고 두 번째 페이지로 리다이렉트 한다. protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { if (Request.QueryString["AcceptsCookies"] == null) { Response.Cookies["TestCookie"].Value = "ok"; Response.Cookies["TestCookie"].Expires = DateTime.Now.AddMinutes(1); Response.Redirect("TestForCookies.aspx?redirect=" + Server.UrlEncode(Request.Url.ToString())); } else { Label1.Text = "Accept cookies = " + Server.UrlEncode( Request.QueryString["AcceptsCookies"]); } } } //두 번째 페이지 (쿠키를 읽어보고 허용 유/무를 판단하여 다시 첫번째 페이지로 이동한다) protected void Page_Load(object sender, EventArgs e) { string redirect = Request.QueryString["redirect"]; string acceptsCookies; if(Request.Cookies["TestCookie"] ==null) acceptsCookies = "no"; else { acceptsCookies = "yes"; // Delete test cookie. Response.Cookies["TestCookie"].Expires = DateTime.Now.AddDays(-1); } Response.Redirect(redirect + "?AcceptsCookies=" + acceptsCookies, true); } |
Msdn 이 이러한 두 페이지에 걸친 처리보다는 클라이언트 스크립트로 처리하는 것이 더 좋을 때도 있다.
다음처럼…
<script language="JavaScript"> <!-- function ReadCookie(cookieName) { var theCookie=""+document.cookie; var ind=theCookie.indexOf(cookieName); if (ind==-1 || cookieName=="") return ""; var ind1=theCookie.indexOf(';',ind); if (ind1==-1) ind1=theCookie.length; return unescape(theCookie.substring(ind+cookieName.length+1,ind1)); } function SetCookie(cookieName,cookieValue,nDays) { var today = new Date(); var expire = new Date(); if (nDays==null || nDays==0) nDays=1; expire.setTime(today.getTime() + 3600000*24*nDays); document.cookie = cookieName+"="+escape(cookieValue) + ";expires="+expire.toGMTString(); } //--> </script> <script language="JavaScript"> <!-- testValue=Math.floor(1000*Math.random()); SetCookie('AreCookiesEnabled',testValue); if (testValue==ReadCookie('AreCookiesEnabled')) document.write('<b>현재고객님의 브라우져에는 쿠키가허용되어있습니다.</b>') else document.write('<b>현재 고객님의 브루우져에 쿠키허용이 금지되어있습니다. </b>') //--> </script> |
이 스크립트 코드는 asp.net 에서의 체크 시나리오와 동일하다. 단지 클라이언트에서 실행되는 것이라서 불 필요한 라운드 트립 이 발생하지 않는다는 장점이 있다.
샘플 코드의 해석은 중요치 않다. 단지 이러한 방법으로 확인하는 시나리오가 있을 수 있다는 것이 중요하다.
6. 기타 참고 사항
쿠키는 http 프로토콜의 헤더에 포함되어 진다.
아래 그림은 쿠키를 저장할 때의 http 헤더 정보이다.
자세한 http 헤더 정보는 다음 링크에서 확인 하자.
또한 하위 키가 있는 쿠키의 정보 변경 시 주의할 사항에 대해서는 다음 링크에서 확인 하자.
7. 쿠키.. 보안에 유의 하라.
쿠키는 정보 유지를 위해 클라이언트에 의존 하는 편하고도 좋은 방법이다.
그러나 모든 것은 얻는 것이 있으면 잃는 것 또한 있는 법이다.
기본적으로 쿠키는 클라이언트 pc에 txt 파일 형태로 저장되기 때문에 보안상 좋지 않다.
만일 중요한 정보를 평문 형태로 저장 한다면 이건 거의 자살행위나 마찬 가지다.
또한 적절한 암호화를 수행했다고 하여도 안정성은 보장 할 수 없다.
나아가 Key=Value 형태를 그대로 저장하는 것에도 문제가 있다.
가장 기본은 중요한 정보는 쿠키에 의존하면 안 된다 이다.
그러나 만일 불가피하게 약간은 중요한 정보를 쿠키에 저장해야만 할 경우에는 적절한 암호화를 수행하도록 한다.
또한 key=value 패턴을 사용하지 않도록 한다. 그리고 악의의 사용자가 특정 범위를 쉽게 알아내어 복호화 하는 것을 미연에 방지하도록 한다.
쿠키 변조와 관련된 내용은 아래 링크에서 확인 하자.
'Program > ASP.NET' 카테고리의 다른 글
ASP.NET AJAX로 만드는 RSS Viewer - Part2 [ASP.NET] (0) | 2009.06.16 |
---|---|
ASP.NET AJAX로 만드는 RSS Viewer - Part1 [ASP.NET] (0) | 2009.06.16 |
페이지 공통 요소 분리하기 (0) | 2009.04.24 |
System.Security.SecurityException: 요청한 레지스트리에 액세스할 수 없습니다 (0) | 2009.04.24 |
ASP.NET에서 다중쿠키 수정시 주의점 (0) | 2009.04.24 |