Mike Pope
Visual Basic 사용자 교육
Microsoft Corporation

2003년 1월

요약: ASP.NET 웹 응용 프로그램에서 Visual Basic을 사용하여 HTTP 쿠키를 읽고 작성하는 방법을 설명합니다(18페이지/인쇄 페이지 기준).

적용 대상

  • ASP.NET
  • Microsoft Visual Studio .NET
  • Web Forms

수준: 초보 웹 프로그래머

목차

소개
쿠키란 무엇입니까?
쿠키 제한 사항
쿠키 작성
다중 값 쿠키(하위 키)
쿠키 범위 제어
쿠키 읽기
쿠키 수정 및 삭제
쿠키 및 보안
브라우저의 쿠키 사용 여부 확인
쿠키 및 세션 상태

소개

쿠키는 웹 응용 프로그램에서 사용자 관련 정보를 저장하는 유용한 방법을 제공합니다. 예를 들어, 사용자가 사이트를 방문하면 쿠키를 사용하여 사용자 기본 설정이나 기타 정보를 저장할 수 있습니다. 사용자가 나중에 웹 사이트를 방문하면 응용 프로그램에서 이전에 저장한 정보를 검색할 수 있습니다.

이 문서에서는 ASP.NET 응용 프로그램에서의 쿠키 작업에 대해 간략히 설명합니다. 쿠키를 작성한 다음 나중에 다시 읽기와 같이 ASP.NET에서 쿠키로 작업을 하는 방법을 보여 주고 쿠키의 여러 가지 기능과 경우에 따른 문제점 및 ASP.NET에서의 쿠키 지원에 대해 설명합니다.

쿠키란 무엇입니까?

쿠키는 웹 서버와 브라우저 사이를 이동할 때 요청과 페이지를 함께 포함하는 작은 텍스트 비트입니다. 쿠키에는 사용자가 사이트를 방문할 때마다 웹 응용 프로그램에서 읽을 수 있는 정보가 들어 있습니다.

사용자가 www.contoso.com 사이트에서 페이지를 요청했을 때 응용 프로그램이 페이지는 보내지 않고 날짜와 시간이 들어 있는 쿠키만 보낸다고 가정해 봅시다. 사용자의 브라우저에 페이지가 표시되면 사용자의 하드 디스크에 있는 폴더에 저장되는 쿠키도 브라우저에 표시됩니다.

나중에 사용자가 사이트에서 페이지를 다시 요청합니다. 사용자가 URL, www.contoso.com을 입력하면 브라우저는 로컬 하드 디스크에서 이 URL과 관련된 쿠키를 찾습니다. 해당 쿠키가 있으면 브라우저는 해당 쿠키를 페이지 요청과 함께 사이트로 보냅니다. 그러면 응용 프로그램은 사용자가 마지막으로 사이트를 방문한 날짜와 시간을 확인할 수 있습니다. 이 정보를 사용하여 사용자에게 메시지를 표시하거나 만료 날짜를 확인하거나 기타 유용한 기능을 수행할 수 있습니다.

쿠키는 특정 페이지와 연결된 것이 아니라 웹 사이트와 연결되어 있으므로 브라우저와 서버는 사용자가 사이트에서 요청하는 페이지에 관계 없이 www.contoso.com 쿠키 정보를 교환할 수 있습니다. 사용자가 다른 사이트를 방문하면 각 사이트는 사용자의 브라우저에도 쿠키를 보내며, 브라우저는 모든 쿠키를 별도로 저장합니다.

이것이 쿠키의 기본 작동 방식입니다. 그러면 쿠키가 어디에 유용합니까? 원래 쿠키는 웹 사이트에서 방문자에 대한 정보를 저장할 수 있도록 합니다. 다시 말하면 쿠키는 웹 응용 프로그램에서 연속성을 유지(이전에는 상태 관리 수행)하는 한 방법입니다. 실제로 정보가 교환되는 잠깐 동안을 제외하고는 브라우저와 웹 서버의 연결은 끊어집니다. 웹 서버에 대한 각각의 요청은 다른 요청과 독립적으로 처리됩니다. 그러나 대부분의 경우 쿠키는 사용자가 페이지를 요청할 때 웹 서버에서 해당 사용자를 인식하는 데 유용합니다. 예를 들면, 쇼핑 사이트의 웹 서버는 개별 쇼핑자를 추적하므로 사이트에서 장바구니와 기타 사용자 관련 정보를 관리할 수 있습니다. 따라서 쿠키는 일종의 전화 카드처럼 작동하여 응용 프로그램이 진행 방법을 알 수 있게 해주는 관련 ID를 나타냅니다.

쿠키는 웹 사이트에서 사용자를 기억할 수 있도록 해주는 것과 관련된 모든 용도로 사용됩니다. 예를 들면, 투표를 수행하는 사이트는 사용자의 브라우저가 투표에 참여했는지 여부를 나타내기 위해 부울 값으로 쿠키를 사용하므로 사용자가 두 번 투표하지 않게 됩니다. 로그온하도록 요청하는 사이트는 사용자가 이미 로그온했는지 확인하는 데 쿠키를 사용하므로 자격 증명을 계속해서 입력하지 않아도 됩니다.

쿠키에 대한 자세한 내용은 Verizon 웹 사이트, http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html  에서 "How Internet Cookies Work" 기사를 참조하십시오. 쿠키란 무엇이고 브라우저와 서버 간에 쿠키를 교환하는 방법을 자세히 설명하고, 쿠키에 관련된 개인 정보 문제에 대해 간략히 설명합니다.

왜 "쿠키"라고 하는지 궁금하신 적이 있습니까? New Hacker's Dictionary(신 해커 사전)라고도 하는 Jargon File(전문어 목록) 버전 4.3.3에 용어의 어원에 대한 정의와 적절한 설명이 있습니다. http://www.catb.org/~esr/jargon/jargon.html#cookie  에서 항목을 찾을 수 있습니다.

이제 여기서부터는 쿠키가 무엇인지, 왜 ASP.NET 응용 프로그램에서 쿠키를 사용하는지에 대해 알고 있다고 가정합니다.

쿠키 제한 사항

쿠키 작업 방법에 대한 설명을 시작하기 전에 쿠키 작업에 대한 제한 사항을 먼저 언급하겠습니다. 대부분의 브라우저는 최대 4096바이트의 쿠키를 지원합니다. 이 정도 크기의 공간이면 사용자의 컴퓨터에 값을 저장하는 데 충분하지만 데이터 집합이나 기타 큰 데이터를 쿠키에 저장하지 못할 수도 있습니다. 실제로 많은 사용자 정보를 쿠키에 저장하지 않고, 대신 사용자 번호나 다른 식별자를 저장할 수 있습니다. 그러면 사용자가 사이트를 다시 방문했을 때 사용자 ID를 사용하여 데이터베이스에서 사용자 세부 사항을 조회할 수 있습니다. 사용자 정보 저장에 대한 주의 사항은 쿠키 및 보안을 참조하십시오.

브라우저에서도 사이트에서 사용자 컴퓨터에 저장할 수 있는 쿠키 수를 제한합니다. 대부분의 브라우저에서는 사이트마다 20개의 쿠키를 허용합니다. 쿠키를 더 많이 저장하려고 하면 가장 오래된 쿠키가 삭제됩니다. 일부 브라우저는 연결된 모든 사이트에서 허용하는 쿠키 수를 일반적으로 300개로 제한합니다.

일반적인 쿠키 제한 사항은 쿠키를 사용하지 않도록 사용자가 브라우저를 설정할 수 있다는 것입니다. 이 문제를 해결하려면 쿠키를 함께 사용하지 않고 다른 방법으로 사용자 관련 정보를 저장하는 방법 밖에 없습니다. 사용자 정보를 저장하는 일반적인 방법은 세션 상태이지만, 뒷부분에 있는 쿠키 및 세션 상태에 설명한 대로 세션 상태는 쿠키에 따라 다릅니다.

참고   웹 응용 프로그램에서 정보 저장의 옵션 및 상태 관리에 대한 자세한 내용은 Introduction to Web Forms State Management  및 State Management Recommendations  를 참조하십시오.

쿠키가 응용 프로그램에서 매우 유용할 수 있지만 응용 프로그램이 쿠키 저장 가능 여부에 의존하지 않아야 한다는 것이 중요합니다. 유용한 기능에는 쿠키를 사용하고 중요한 기능을 지원하는 데는 쿠키를 사용하지 마십시오. 응용 프로그램이 쿠키에 의존해야 할 경우 브라우저에서 쿠키를 사용하는지 여부는 테스트를 통해 확인할 수 있습니다. 이 문서 뒷부분에 있는 브라우저의 쿠키 사용 여부 확인 절에서 테스트 방법을 간략히 소개합니다.

쿠키 작성

페이지의 Response  속성을 사용하여 쿠키를 작성합니다. 이 속성은 페이지에서 브라우저에 렌더링하는 정보에 추가할 수 있는 개체를 제공합니다. Response 개체는 브라우저에 작성하려는 쿠키를 추가하는 Cookies  라는 컬렉션을 지원합니다.

참고   Response 개체와 Request 개체는 각각 HttpResponse  클래스와 HttpRequest  클래스의 인스턴스가 들어 있는 페이지 속성입니다. 이 개체에 대해서는 간략히 설명하겠습니다. 설명서에서 ResponseRequest에 대한 정보를 찾으려면 HttpResponseHttpRequest에서 찾으십시오.

쿠키를 만들 때 여러 가지 값을 지정합니다. 쿠키를 만들려면 쿠키 이름과 쿠키에 저장할 값을 지정합니다. 여러 개의 쿠키를 만들 수 있으므로 각 쿠키에 고유한 이름이 있어야 나중에 읽을 때 쿠키를 식별할 수 있습니다. 쿠키는 이름으로 저장되므로 이름이 같은 두 개의 쿠키를 만들 경우 한 쿠키가 다른 쿠키를 덮어씁니다.

쿠키 만료 날짜와 시간을 지정할 수도 있습니다. 쿠키는 일반적으로 사용자의 디스크에 작성되며 이 디스크에 영구적으로 존재할 수 있습니다. 그러므로 쿠키가 만료되는 날짜와 시간을 지정할 수 있습니다. 사용자가 사이트를 다시 방문하면 브라우저는 먼저 사이트의 쿠키 컬렉션을 검사합니다. 쿠키가 만료되면 브라우저는 페이지를 요청한 서버에 특정 쿠키를 보내지 않습니다. 대신 만료된 쿠키가 삭제됩니다. 사이트에서 여러 개의 쿠키를 사용자의 컴퓨터에 작성했을 수 있으며, 쿠키마다 별도의 만료 날짜와 시간이 있을 수 있습니다. 브라우저는 하드 디스크의 쿠키 관리를 담당하며, 응용 프로그램에서 쿠키로 할 수 있는 작업에 영향을 줍니다. 여기에 대해서는 간략히 설명하겠습니다.

한 쿠키의 만료 기간은 얼마나 됩니까? 이 기간은 쿠키를 사용하는 대상에 따라 다르며, 응용 프로그램이 쿠키 값을 유효한 것으로 간주하는 기간에 따라 다릅니다. 쿠키를 사용하여 사이트 방문자 수를 계산할 경우 어떤 사용자가 사이트를 1년 동안 방문하지 않으면 그 사용자를 새 방문자로 간주하다는 전제 하에 만료 기간을 현재부터 1년까지로 설정할 수 있습니다. 이와 반대로 사용자 기본 설정을 저장하는 데 쿠키를 사용할 경우 사용자가 기본 설정을 정기적으로 재설정하는 것이 번거로우므로 만료 기간이 만료되지 않도록 설정(예: 50년)할 수 있습니다. 분 또는 초 단위로 만료되는 쿠키를 작성할 수도 있습니다. 이 문서 뒷부분에 나오는 브라우저의 쿠키 사용 여부 확인 절에는 실제 사용 기간이 초 단위로 측정되는 쿠키를 만드는 예제가 있습니다.

참고   사용자는 언제든지 컴퓨터에서 쿠키를 지울 수 있습니다. 만료 기간이 긴 쿠키를 저장해도 사용자가 쿠키를 모두 삭제할 수 있으므로 쿠키에 저장한 설정이 지워질 수 있습니다.

쿠키 만료 기간을 설정하지 않으면 쿠키는 만들어지지만 사용자의 하드 디스크에 저장되지 않습니다. 대신 사용자의 세션 정보의 일부로 쿠키가 유지 관리됩니다. 사용자가 브라우저를 닫거나 세션 제한 시간이 초과되면 쿠키가 삭제됩니다. 이와 같은 비영구적인 쿠키는 짧은 시간 동안만 저장해야 하는 정보나, 보안상의 이유로 클라이언트 컴퓨터의 디스크에 작성하지 않아야 하는 정보에 유용합니다. 예를 들어, 비영구적인 쿠키는 디스크에 쿠키를 작성하지 않아도 되는 공용 컴퓨터에서 작업할 경우 유용합니다.

두 가지 방법으로 Response.Cookies 컬렉션에 쿠키를 추가할 수 있습니다. 다음 예제는 이 작업을 수행하는 두 가지 방법을 보여 줍니다.

Response.Cookies("userName").Value = "mike" Response.Cookies("userName").Expires = DateTime.Now.AddDays(1) Dim aCookie As New HttpCookie("lastVisit") aCookie.Value = DateTime.Now.ToString aCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(aCookie)

이 예제에서는 "userName" 쿠키와 "lastVisit"라는 쿠키를 Cookies 컬렉션에 추가합니다. 첫 번째 쿠키의 경우 Response.Cookies 컬렉션 값을 직접 설정했습니다. Response.CookiesNameObjectCollectionBase  라는 특수 컬렉션 유형에서 파생되므로 이러한 방법으로 컬렉션에 값을 추가할 수 있습니다.

두 번째 쿠키의 경우 쿠키 개체의 인스턴스(HttpCookie  유형)를 만들어 속성을 설정한 다음 Add 메서드를 통해 Response.Cookies 컬렉션에 추가합니다. HttpCookie 개체를 인스턴스화하면 쿠키 이름을 생성자의 일부로 전달해야 합니다.

두 예제 모두는 같은 작업을 수행합니다. 즉, 쿠키를 브라우저에 작성합니다. 사용 방법은 주로 개인의 취향에 따라 다릅니다. 두 번째 방법으로 쿠키 속성을 설정하는 것이 좀 더 쉽지만 큰 차이는 없습니다.

두 방법 모두 만료 값이 DateTime 유형이어야 합니다. 그러나 "lastVisited" 값이 날짜-시간 값일 수도 있습니다. 그러나 이 경우 날짜-시간 값을 문자열로 변환해야 합니다. 쿠키에 저장하는 모든 값은 결국 문자열로 저장됩니다.

쿠키 보기

쿠키를 만든 효과를 확인하는 데 유용합니다. 쿠키는 텍스트 파일이므로 쿠키를 찾을 수 있으면 쉽게 볼 수 있습니다. 브라우저마다 쿠키를 저장하는 방법이 다릅니다. Internet Explorer가 쿠키를 저장하는 방법을 설명하겠습니다. 다른 브라우저를 사용하는 경우 해당 브라우저의 도움말을 확인하여 쿠키 처리 방법을 확인하십시오.

쿠키를 쉽게 보는 방법은 사용자 대신 Internet Explorer가 쿠키를 찾는 것입니다. Internet Explorer의 [도구] 메뉴에서 [인터넷 옵션]을 선택합니다. [일반] 탭에서 [설정]을 클릭한 다음 [파일 보기]를 클릭합니다. Internet Explorer는 쿠키를 비롯한 해당 임시 파일을 모두 표시하는 창을 엽니다. 창에서 이름이 "Cookie:"로 시작하는 파일을 찾거나 텍스트 파일을 찾습니다. 쿠키를 두 번 눌러 기본 텍스트 파일에서 엽니다.

또는 하드 디스크에서 해당 텍스트 파일을 찾아서 쿠키를 탐색할 수 있습니다. Internet Explorer는 이름이 <user>@<domain>.txt 형식(여기서, <user>는 계정 이름)인 파일에 사이트의 쿠키를 저장합니다. 예를 들어, 사용자 이름이 mikepope이고 www.contoso.com 사이트를 방문한 경우 이 사이트의 쿠키는 mikepope@www.contoso.txt라는 파일에 저장됩니다. 이 이름에 mikepope@www.contoso[1].txt와 같이 일련 번호가 포함될 수 있습니다.

쿠키 텍스트 파일은 사용자마다 고유하므로 계정으로 구분됩니다. 예를 들어, Windows XP에서는 이름이 다음과 같은 디렉터리에서 쿠키 파일을 찾습니다.

c:\Documents and Settings\<user>\Cookies

만들고 있는 쿠키를 찾으려면 수정한 날짜별로 디렉터리를 정렬하고 최신 파일을 찾는 것이 유용합니다.

텍스트 편집기에서 쿠키를 열 수 있습니다. 파일에 여러 개의 쿠키가 있을 경우 별표(*)로 구분됩니다. 각 쿠키의 첫 번째 줄은 쿠키 이름이고 두 번째 줄에 값이 있습니다. 나머지 줄에 만료 날짜 및 시간과 같은 쿠키 유지 정보가 있습니다. 또한 쿠키에는 간단한 체크섬이 있습니다. 쿠키 이름이나 값의 길이를 변경하면 브라우저는 이 변경 사항을 검색하고 쿠키를 삭제합니다.

다중 값 쿠키(하위 키)

위의 예제에서는 저장할 각 값에 하나의 쿠키를 사용합니다(사용자 이름, 마지막 방문 날짜). 또한 단일 쿠키에 여러 개의 이름-값 쌍을 저장할 수 있습니다. 이름-값 쌍은 읽고 있는 항목에 따라 "키" 또는 "하위 키"라고 합니다. 하위 키는 URL의 쿼리 문자열과 거의 구조가 같으므로 이 구조를 잘 알고 있어야 합니다. 예를 들어, "userName" 및 "lastVisit"라는 두 개의 쿠키를 별도로 만들지 않고 "userName"과 "lastVisit" 하위 키가 있는 "userInfo"라는 단일 쿠키를 만들 수 있습니다.

별도의 쿠키를 만들지 않고 하위 키를 사용하는 이유가 두 가지 있습니다. 관련된 정보나 비슷한 정보를 단일 쿠키에 두는 것이 편리하며 모든 정보가 단일 쿠키에 있기 때문에 만료와 같은 쿠키 특성이 모든 정보에 적용됩니다. 이와 반대로 여러 만료 날짜를 다른 유형의 정보에 할당하려면 별도의 쿠키에 정보를 저장해야 합니다.

하위 키가 있는 쿠키를 통해 쿠키 크기를 줄일 수 있습니다. 앞부분의 쿠키 제한 사항에 언급했듯이 쿠키는 4096바이트로 제한되므로 사이트마다 20개 이상의 쿠키를 저장할 수 없습니다. 하위 키가 있는 단일 쿠키를 사용하면 사이트에 할당된 20개의 쿠키를 거의 사용하지 않을 수 있습니다. 또한 단일 쿠키는 오버헤드(예: 만료 정보 등)에 대해 최대 50자 정도 그리고 이 오버헤드에 저장하는 값의 길이를 합하여 모두 약 4K로 제한됩니다. 다섯 개의 별도 쿠키 대신 다섯 개의 하위 키를 저장하면 개별 쿠키의 오버헤드를 줄일 수 있으며 200바이트 정도 줄일 수 있습니다.

하위 키가 있는 쿠키를 만들기 위해 단일 쿠키를 작성하는 구문을 변형하여 사용할 수 있습니다. 다음 예제는 각각 두 개의 하위 키가 있는 동일한 쿠키를 작성하는 두 가지 방법을 보여 줍니다.

Response.Cookies("userInfo")("userName") = "mike" Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1) Dim aCookie As New HttpCookie("userInfo") aCookie.Values("userName") = "mike" aCookie.Values("lastVisit") = DateTime.Now.ToString aCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(aCookie)

쿠키 범위 제어

기본적으로 한 사이트의 모든 쿠키는 클라이언트에 함께 저장되고 모든 쿠키는 해당 사이트에 대한 요청과 함께 서버로 전송됩니다. 즉, 한 사이트의 모든 페이지가 해당 사이트에 대한 쿠키를 모두 가져옵니다. 하지만 쿠키 동작을 좀 더 자세히 지정해야 하는 경우도 있습니다. 다음 두 가지 방법으로 쿠키 범위를 설정할 수 있습니다.

  • 쿠키 범위를 서버의 한 폴더로 제한합니다. 이렇게 하면 실제로 쿠키를 사이트의 응용 프로그램으로 제한할 수 있습니다.
  • 범위를 도메인으로 설정합니다. 이렇게 하면 쿠키에 액세스할 수 있는 도메인의 하위 도메인을 지정할 수 있습니다.

쿠키를 폴더나 응용 프로그램으로 제한

쿠키를 서버의 한 폴더로 제한하려면 쿠키의 Path 속성을 다음과 같이 설정합니다.

Dim appCookie As New HttpCookie("AppCookie") appCookie.Value = "written " & Now.ToString appCookie.Expires = Now.AddDays(1) appCookie.Path = "/Application1" Response.Cookies.Add(appCookie)

앞에서 설명했듯이 Response.Cookies를 직접 설정하여 쿠키를 작성할 수도 있습니다.

경로는 사이트 루트 아래의 실제 경로이거나 가상 경로일 수 있습니다. 그 결과로 쿠키를 Application1 폴더나 가상 루트의 페이지에서만 사용할 수 있습니다. 예를 들어, 사이트를 www.contoso.com으로 호출하면 이전 예제에서 만든 쿠키는 http://www.contoso.com/Application1/ 경로의 페이지와 이 폴더의 바로 아래 페이지에 사용할 수 있습니다. 그러나 http://www.contoso.com/Application2/ 같은 다른 응용 프로그램이나 http://www.contoso.com/에 이 쿠키를 사용할 수 없습니다.

   Internet Explorer와 Mozilla 브라우저를 테스트한 결과 경로가 대/소문자를 구분하는 것이 좋습니다. 일반적으로 Windows 서버의 URL은 대/소문자를 구분하지 않지만 이 경우 예외입니다. 사용자가 자신의 브라우저에 URL을 입력하는 방법을 제어할 수 없지만 응용 프로그램이 특정 경로에 연결된 쿠키에 의존할 경우 만든 하이퍼링크의 URL이 Path 속성 값의 대/소문자와 일치하는지 확인하십시오.

쿠키 범위를 도메인으로 제한

기본적으로 쿠키는 특정 도메인과 연결됩니다. 예를 들어, 사이트가 www.contoso.com인 경우 사용자가 이 사이트에서 페이지를 요청하면 작성한 쿠키는 서버로 전송됩니다. 바로 앞 절에서 설명했듯이 특정 경로 값이 있는 쿠키는 제외됩니다. 사이트에 하위 도메인이 있을 경우(예: contoso.com, sales.contoso.com, support.contoso.com) 쿠키와 특정 하위 도메인을 연결할 수 있습니다. 이렇게 하려면 쿠키의 Domain 속성을 다음과 같이 설정합니다.

Response.Cookies("domain").Value = DateTime.Now.ToString Response.Cookies("domain").Expires = DateTime.Now.AddDays(1) Response.Cookies("domain").Domain = "support.contoso.com"

도메인이 이러한 방식으로 설정되어 있으면 지정된 하위 도메인의 페이지에서만 쿠키를 사용할 수 있습니다.

Domain 속성을 사용하여 여러 하위 도메인 간에 공유할 수 있는 쿠키를 만들 수도 있습니다. 예를 들면, 다음과 같이 도메인을 설정합니다.

Response.Cookies("domain").Value = DateTime.Now.ToString Response.Cookies("domain").Expires = DateTime.Now.AddDays(1) Response.Cookies("domain").Domain = "contoso.com"

그러면 쿠키를 sales.contoso.com과 support.contoso.com뿐만 아니라 주 도메인에서도 사용할 수 있습니다.

쿠키 읽기

브라우저가 서버에 요청하면 브라우저는 해당 서버의 쿠키를 요청과 함께 보냅니다. ASP.NET 응용 프로그램에서 Request 개체를 사용하여 쿠키를 읽을 수 있습니다. Request 개체의 구조는 Response 개체의 구조와 같으므로 Response 개체에 쿠키를 작성하는 방법으로 Request 개체에서 쿠키를 읽을 수 있습니다. 다음 예제는 "username"이라는 쿠키 값을 가져오고 그 값을 Label 컨트롤로 표시하는 방법을 보여 줍니다.

If Not Request.Cookies("userName") Is Nothing Then Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value) End If If Not Request.Cookies("userName") Is Nothing Then Dim aCookie As HttpCookie = Request.Cookies("userName") Label1.Text = Server.HtmlEncode(aCookie.Value) End If

쿠키 값을 가져오기 전에 쿠키가 있는지 확인해야 합니다. 그렇지 않으면 System.NullReferenceException  예외가 발생합니다. 쿠키의 콘텐트를 인코딩하는 HttpServerUtility.HtmlEncode  메서드를 호출한 후 페이지에 표시하십시오. 일반적으로는 이렇게 하지 않지만 쿠키의 콘텐트를 현재 표시하고 있기 때문에 그리고 악의적인 사용자가 실행 스크립트를 몰래 쿠키에 넣지 않도록 하기 위해 여기서 이 작업을 수행합니다. 쿠키 보안에 대한 자세한 내용은 쿠키 및 보안을 참조하십시오.

참고   브라우저마다 쿠키를 다르게 저장하므로 같은 컴퓨터에 있는 한 브라우저에서 다른 브라우저의 쿠키를 반드시 읽을 수 있어야 할 필요는 없습니다. 예를 들어, Internet Explorer를 사용하여 한 번에 한 페이지를 테스트하고 나중에 다른 브라우저를 사용하여 다시 테스트할 경우 나중에 사용한 브라우저는 Internet Explorer에서 저장한 쿠키를 찾을 수 없습니다. 물론 대부분의 사용자는 자신의 웹 상호 작용에 같은 브라우저를 사용하므로 대부분의 환경에서 이것은 문제가 되지 않습니다. 그러나 응용 프로그램에서 브라우저 호환성을 테스트하는 경우에는 이러한 문제가 발생할 수 있습니다.

쿠키의 하위 키 값을 읽는 방법은 하위 키 값을 설정하는 방법과 비슷합니다. 다음은 하위 키 값을 얻는 방법입니다.

If Not Request.Cookies("userInfo") Is Nothing Then Label1.Text = _ Server.HtmlEncode(Request.Cookies("userInfo")("userName")) Label2.text = _ Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit")) End If

앞의 예제에서는 이전에 DateTime 값의 문자열 표현으로 설정한 "lastVisit" 하위 키 값을 가져옵니다. 쿠키는 값을 문자열로 저장하므로 lastVisit 값을 날짜로 사용하려면 변환해야 합니다.

Dim dt As DateTime dt = CDate(Request.Cookies("userInfo")("lastVisit"))

쿠키의 하위 키는 NameValueCollection  형식의 컬렉션으로 입력됩니다. 따라서 개별 하위 키를 가져오는 다른 방법은 아래에서처럼 하위 키 컬렉션을 가져온 다음 이름별로 하위 키 값을 추출하는 것입니다.

If Not Request.Cookies("userInfo") Is Nothing Then Dim UserInfoCookieCollection As _ System.Collections.Specialized.NameValueCollection UserInfoCookieCollection = Request.Cookies("userInfo").Values Label1.Text = Server.HtmlEncode(UserInfoCookieCollection("userName")) Label2.Text = Server.HtmlEncode(UserInfoCookieCollection("lastVisit")) End If

쿠키 설정과 마찬가지로 쿠키를 읽을 때 사용하는 방법은 사용자가 선택할 수 있습니다.

만료란 무엇입니까?

쿠키 이름과 값을 읽을 수 있지만 쿠키에 대한 정보는 많지 않습니다. DomainPath 속성을 가져올 수 있지만 그러한 속성은 사용이 제한되어 있습니다. 예를 들면, Domain 속성을 읽을 수 있지만 페이지가 쿠키와 같은 도메인에 있지 않을 경우 처음부터 쿠키를 받지 않게 됩니다.

쿠키의 만료 날짜와 시간은 읽을 수 없습니다. 브라우저에서 쿠키 정보를 서버로 보낼 때 브라우저에서 만료 정보를 포함하지 않는 것으로 나타났습니다. Expires 속성을 읽을 수 있지만 항상 날짜-시간 값 0을 반환합니다.

앞부분에 있는 쿠키 작성에서 브라우저가 쿠키 관리를 담당한다고 언급했습니다. Expires 속성은 이러한 예입니다. Expires 속성의 주요 용도는 브라우저가 쿠키를 저장소에 유지할 수 있도록 하는 것입니다. 서버의 관점에서 쿠키는 존재하거나 존재하지 않습니다. 서버 측에서는 만료가 유용한 정보가 아닙니다. 따라서 브라우저가 쿠키를 보낼 때 이 정보를 제공하지 않습니다. 쿠키 만료 날짜가 중요한 경우 만료 날짜를 재설정해야 합니다. 쿠키 수정 및 삭제에서 간략히 설명하겠습니다.

명확히 말하면 쿠키가 브라우저에 전송되기 전에 Response 개체에 설정한 쿠키의 Expires 속성을 읽을 수 있습니다. 그러나 Request 개체에서 만료일을 다시 가져올 수 없습니다.

쿠키 컬렉션 읽기

위 예에서는 이름을 알고 있는 특정 쿠키를 읽으려고 한다고 가정합니다. 페이지에 사용할 수 있는 모든 쿠키를 읽어야 하는 경우도 있습니다. 페이지에 사용할 수 있는 모든 쿠키의 이름과 값을 읽으려면 다음과 같은 코드를 사용하여 Request.Cookies 컬렉션을 반복할 수 있습니다.

Dim i As Integer Dim output As String = "" Dim aCookie As HttpCookie For i = 0 to Request.Cookies.Count - 1 aCookie = Request.Cookies(i) output &= "쿠키 이름 = " & Server.HtmlEncode(aCookie.Name) & "<br>" output &= "쿠키 값 = " & Server.HtmlEncode(aCookie.Value) & _ & "<br><br>" Next Label1.Text = output
참고   이 코드를 실행하면 "ASP.NET_SessionId"라는 쿠키가 표시됩니다. 이 쿠키는 ASP.NET에서 사용자 세션에 대한 고유 식별자를 저장하는 데 사용합니다. 세션 쿠키는 하드 디스크에 유지되지 않습니다. 세션 쿠키에 대한 자세한 내용은 이 문서 뒷부분에 있는 쿠키 및 세션 상태를 참조하십시오.

앞의 예제에는 쿠키에 하위 키가 있으면 디스플레이에서 단일 이름/값 문자열로 하위 키를 표시하는 제한이 있습니다. 쿠키 속성 HasKeys  는 쿠키에 하위 키가 있는지 여부를 알려 줍니다. 쿠키에 하위 키가 있으면 하위 키 컬렉션으로 드릴다운하여 개별 하위 키 이름과 값을 얻을 수 있습니다.

앞에서 언급했듯이 NameValueCollection 형식의 컬렉션인 Values  쿠키 속성에서 하위 키에 대한 정보를 가져올 수 있습니다. Values 컬렉션에서 인덱스 값으로 직접 하위 키 값을 읽을 수 있습니다. 해당 하위 키 이름은 문자열 컬렉션을 반환하는 Values 컬렉션의 AllKeys  멤버에서 사용할 수 있습니다.

다음 예제는 이전 예제의 수정 사항을 보여 줍니다. HasKeys 속성을 사용하여 하위 키를 테스트하고 하위 키가 검색되면 Values 컬렉션에서 하위 키를 가져옵니다.

Dim i As Integer Dim j As Integer Dim output As String = "" Dim aCookie As HttpCookie Dim subkeyName As String Dim subkeyValue As String For i = 0 To Request.Cookies.Count - 1 aCookie = Request.Cookies(i) output &= "이름 = " & aCookie.Name & "<br>" If aCookie.HasKeys Then For j = 0 To aCookie.Values.Count - 1 subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j)) subkeyValue = Server.HtmlEncode(aCookie.Values(j)) output &= "하위 키 이름 = " & subkeyName & "<br>" output &= "하위 키 값 = " & subkeyValue & "<br><br>" Next Else output &= "값 = " & Server.HtmlEncode(aCookie.Value) & "<br><br>" End If Next Label1.Text = output

또는 다음과 같이 하위 키를 NameValueCollection 개체로 추출할 수 있습니다.

If aCookie.HasKeys Then Dim CookieValues As _ System.Collections.Specialized.NameValueCollection = aCookie.Values Dim CookieValueNames() As String = CookieValues.AllKeys For j = 0 To CookieValues.Count – 1 subkeyName = Server.HtmlEncode(CookieValueNames(j)) subkeyValue = Server.HtmlEncode(CookieValues(j)) output &= "하위 키 이름 = " & subkeyName & "<br>" output &= "하위 키 값 = " & subkeyValue & "<br><br>" Next Else output &= "값 = " & aCookie.Value & "<br><br>" End If
참고   페이지에 쿠키 값을 표시하므로 Server.HtmlEncode 메서드만 호출합니다. 쿠키 값만 테스트하는 경우에는 값을 사용하기 전에 이 값을 인코딩할 필요가 없습니다.

쿠키 수정 및 삭제

쿠키를 수정하려는 경우 쿠키 값을 변경하거나 쿠키 만료일을 연장합니다. 브라우저에서 만료 정보를 서버에 전달하지 않으므로 쿠키의 만료 날짜를 읽을 수 없습니다.

물론 쿠키를 직접 변경하지 않습니다. Request.Cookies 컬렉션에서 쿠키를 가져와서 조작할 수 있지만 쿠키 자체는 사용자의 하드 디스크 어딘가에 활성화되어 있습니다. 그러므로 쿠키를 수정하려면 새 값으로 쿠키를 만든 다음 쿠키를 브라우저로 보내어 클라이언트에 있는 이전 버전을 덮어씁니다.

다음 예제는 사용자의 방문 횟수를 사이트에 저장하는 쿠키의 값을 변경하는 방법을 보여 줍니다.

Dim counter As Integer If Request.Cookies("counter") Is Nothing Then counter = 0 Else counter = CInt(Request.Cookies("counter").Value) End If counter += 1 Response.Cookies("counter").Value = counter.ToString Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)

또는

Dim ctrCookie As HttpCookie Dim counter As Integer If Request.Cookies("counter") Is Nothing Then ctrCookie = New HttpCookie("counter") Else ctrCookie = Request.Cookies("counter") End If counter = CInt(ctrCookie.Value) + 1 ctrCookie.Value = counter.ToString ctrCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(ctrCookie)

쿠키 삭제

쿠키 삭제는 사용자의 하드 디스크에서 쿠키가 실제로 제거되는 것으로, 쿠키 수정에 대한 변형입니다. 쿠키는 사용자의 컴퓨터에 있기 때문에 쿠키를 직접 제거할 수 없습니다. 그러나 브라우저에서 쿠키를 삭제하도록 할 수 있습니다. 방법은 위에 설명된 대로 쿠키를 수정하고(즉 이름이 같은 새 쿠키를 만듬) 쿠키의 만료일을 오늘 이전 날짜로 설정하는 것입니다. 브라우저가 쿠키의 만료일을 검사할 때 브라우저는 오래된 쿠키를 삭제합니다.

따라서 쿠키를 삭제하는 방법은 해당 쿠키를 만드는 방법과 같지만, 삭제하는 경우에는 오늘 이전 날짜를 사용합니다. 다음 예제는 현재 도메인의 모든 쿠키를 삭제하는 방법을 보여 주므로 단일 쿠키를 삭제하는 것보다 흥미롭습니다.

Dim i As Integer Dim cookieName As String Dim limit As Integer = Request.Cookies.Count - 1 For i = 0 To limit aCookie = Request.Cookies(i) aCookie.Expires = DateTime.Now.AddDays(-1) Response.Cookies.Add(aCookie) Next

하위 키 수정 또는 삭제

개별 하위 키를 수정하는 것은 우선 개별 하위 키를 만드는 것과 같습니다.

Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

개별 하위 키를 삭제하는 방법이 훨씬 복잡합니다. 쿠키 만료 날짜를 재설정하면 단일 하위 키가 아닌 쿠키 전체가 제거되므로 간단히 재설정할 수 없습니다. 대신 하위 키를 보유하고 있는 쿠키의 Values 컬렉션을 조작하면 됩니다. 먼저 Request.Cookies 개체에서 쿠키를 가져와서 다시 만듭니다. 그러면 Values 컬렉션의 Remove 메서드를 호출하여 삭제할 하위 키의 이름을 Remove 메서드에 전달합니다. 그런 다음 수정한 쿠키를 Response.Cookies 컬렉션에 추가하여 수정된 양식으로 다시 브라우저에 보냅니다.

다음 코드는 하위 키 삭제 방법을 보여 줍니다. 예제에서 제거할 하위 키 이름은 변수로 지정되었습니다.

Dim subkeyName As String subkeyName = "userName" Dim aCookie As HttpCookie = Request.Cookies("userInfo") aCookie.Values.Remove(subkeyName) aCookie.Expires = DateTime.Now.AddDays(1) Response.Cookies.Add(aCookie)

쿠키 및 보안

쿠키 작업을 하는 경우 쿠키의 본질적인 보안상 취약성을 알고 있어야 합니다. 보안의 경우 개인 정보 문제를 의미하는 것이 아닙니다. 쿠키란 무엇입니까?에서 언급한 기사에 설명된 대로 개인 정보는 쿠키의 정보 사용 방법을 우려하는 사용자에게 보다 중요한 문제입니다. 쿠키 보안 문제는 클라이언트로부터 데이터를 얻는 보안 문제와 비슷합니다. 우선 응용 프로그램의 경우 쿠키는 사용자 입력의 다른 양식이므로 몰래 엿보거나 도용할 수 있습니다. 사용자는 자신의 컴퓨터에서 쿠키를 사용할 수 있으므로 최소한 쿠키에 저장된 데이터를 볼 수 있습니다. 사용자가 쿠키에 저장된 데이터를 보려는 경우 브라우저가 쿠키를 보내기 전에 쿠키를 먼저 변경할 수도 있습니다.

즉, 쿠키에 사용자 이름, 암호, 신용 카드 번호와 같은 중요한 정보는 저장하지 말아야 합니다. 쿠키를 도용할 수 있는 사람이나 사용자가 보지 말아야 할 정보는 쿠키에 두지 마십시오.

마찬가지로 쿠키에서 얻은 정보를 의심하십시오. 데이터가 처음 작성될 때와 같은 상태라고 가정하지 마십시오. 사용자가 웹 페이지에 입력한 데이터가 있는 쿠키 값으로 작업할 때와 같은 보안을 사용하십시오. 예를 들어, 페이지에 값을 표시하기 전에 쿠키의 콘텐트에 HTML 인코딩을 적용합니다. 이 방법은 사용자에게서 정보를 얻은 후에 표시하는 정보를 선별하는 표준 방법이며 쿠키 작업 방법과 다르지 않습니다.

또 다른 문제는 쿠키가 브라우저와 서버 사이에 일반 텍스트로 전송되어 웹 소통량을 차단할 수 있는 사람은 쿠키를 읽을 수 있다는 점입니다. 연결에서 SSL(Secure Sockets Layer 또는 https://)을 사용하는 경우에만 쿠키가 전송되도록 하는 쿠키 속성을 설정할 수 있습니다. SSL은 쿠키가 사용자의 컴퓨터에 있을 때 쿠키를 읽거나 조작할 수 없도록 보호하지는 않지만 전송 중에 쿠키를 차단할 수 없도록 합니다. 이 기사에서는 SSL에 대해 설명하지 않겠습니다. 하지만 쿠키에 전송 보호 기능을 추가할 수 있다는 것은 알아두십시오. SSL에 대한 자세한 내용은 Secure Sockets Layer: Protect Your E-Commerce Web Site with SSL and Digital Certificates  를 참조하십시오.

이러한 보안 문제가 발생한다면 쿠키를 안전하게 사용할 수 있는 방법은 무엇입니까? 사용자 기본 설정이나 응용 프로그램에 중요한 영향을 미치지 않는 기타 정보(손상된 경우)와 같은 중요하지 않은 데이터를 쿠키에 저장할 수 있습니다. 사용자 ID와 같은 중요한 정보를 쿠키에 저장하려는 경우 쿠키를 암호화할 수 있습니다. 한 가지 가능한 방법은 ASP.NET 폼 인증 유틸리티를 사용하여 쿠키로 저장된 인증 티켓을 만드는 것입니다. 이 기사에서는 암호화에 대해 언급하지 않겠습니다. 하지만 쿠키에 중요한 데이터를 저장하려는 경우 엿보거나 위장한 사람으로부터 정보를 보호할 수 있는 가능한 방법을 찾아보십시오.

Mitigating Cross-site Scripting With HTTP-only Cookies  에서 쿠키 및 보안 취약성에 대한 자세한 정보를 찾을 수 있습니다.

브라우저의 쿠키 사용 여부 확인

앞에 나온 쿠키 제한 사항에서 사용자가 브라우저에서 쿠키를 거부하도록 설정했을 수 있는 문제에 대해 언급했습니다. 쿠키를 작성하고 읽을 수 있는지 여부를 어떻게 알 수 있습니까? 페이지가 렌더링된 후에 발생한 문제를 서버에서 추적할 수 없기 때문에 쿠키를 작성할 수 없는 경우 오류가 발생하지 않습니다. 예를 들면, Response.Cookies는 예외를 반환하지 않습니다. 이와 마찬가지로 브라우저에서 서버로 현재 쿠키 설정에 대한 정보를 보내지 않습니다. HttpBrowserCapabilities.Cookies Property  속성은 쿠키 사용 여부를 알려주지 않습니다. 기본적으로 현재 브라우저의 쿠키 지원 여부만 알려 줍니다.

쿠키 사용 여부를 확인하는 한 가지 방법은 쿠키를 작성한 다음 다시 읽어보는 것입니다. 작성한 쿠키를 읽을 수 없으면 해당 브라우저에서 쿠키가 사용되지 않는 것입니다.

쿠키 사용 여부를 테스트하는 방법을 보여 주는 간단한 예제는 다음과 같습니다. 예제는 두 페이지로 구성됩니다. 첫 번째 페이지에서 쿠키를 작성한 다음 브라우저를 두 번째 페이지로 리디렉션합니다. 두 번째 페이지에서 쿠키 읽기를 시도합니다. 다시 브라우저를 첫 번째 페이지로 리디렉션하여 URL에 쿼리 문자열 변수와 함께 테스트 결과를 추가합니다.

첫 번째 페이지의 코드는 다음과 같이 나타납니다.

Sub Page_Load() If Not Page.IsPostBack Then If Request.QueryString("AcceptsCookies") Is Nothing Then Response.Cookies("TestCookie").Value = "ok" Response.Cookies("TestCookie").Expires = _ DateTime.Now.AddMinutes(1) Response.Redirect("TestForCookies.aspx?redirect=" & _ Server.UrlEncode(Request.Url.ToString)) Else labelAcceptsCookies.Text = "쿠키 허용 = " & _ Request.QueryString("AcceptsCookies") End If End If End Sub

해당 페이지에서는 먼저 postback인지 테스트하여 확인하고 아닌 경우 테스트 결과가 포함된 쿼리 문자열 변수(AcceptsCookies)를 찾습니다. 쿼리 문자열 변수가 없을 경우 테스트가 완료되지 않으므로 코드는 "TestCookie"라는 쿠키를 작성합니다. 쿠키를 작성한 후에 테스트 페이지(TestForCookies.aspx)로 전송할 Response.Redirect를 호출합니다. 테스트 페이지의 URL에 현재 페이지의 URL이 포함된 redirect라는 쿼리 문자열 변수를 추가합니다. 이렇게 하면 테스트를 수행한 후에 다시 이 페이지로 리디렉션할 수 있습니다.

테스트 페이지는 완전히 코드로 구성될 수 있으므로 컨트롤을 포함할 필요가 없습니다. 사용한 코드는 다음과 같습니다.

Sub Page_Load() Dim redirect As String = Request.QueryString("redirect") Dim acceptsCookies As String ' 쿠키가 허용되었습니까? If Request.Cookies("TestCookie") Is Nothing Then ' 쿠키가 없으므로 허용되지 않습니다. acceptsCookies = 0 Else acceptsCookies = 1 ' 테스트 쿠키를 삭제합니다. Response.Cookies("TestCookie").Expires = _ DateTime.Now.AddDays(-1) End If Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _ True) End Sub

redirect 쿼리 문자열 변수를 읽은 후에 코드는 쿠키 읽기를 시도합니다. 쿠키를 유지하기 위해 쿠키가 실제로 있으면 즉시 삭제됩니다. 테스트가 완료되면 코드는 전달된 URL에서 새 URL을 redirect 쿼리 문자열 변수에 만듭니다. 또한 새 URL에는 테스트 결과가 있는 쿼리 문자열 변수가 포함되어 있습니다. 마지막 단계는 새 URL을 사용하여 브라우저를 원래 페이지로 리디렉션하는 것입니다.

이 예제는 아주 간단하지만 프로시저를 시도하고 발생한 결과를 표시하여 기본 테스트 원칙을 보여 줍니다. 상당히 향상된 기능은 쿠키 테스트 결과를 영구 저장소에 보관하므로 사용자가 원래 페이지를 볼 때마다 테스트를 반복하지 않아도 되는 것입니다. 그러나 보는 것과 달리 조금 까다롭습니다. 쿠키가 작동하지 않는다면 그에 대한 명백한 이유가 있습니다. 다른 가능성은 테스트 결과를 세션 상태로 저장하는 것이지만, 기본적으로 세션 상태는 쿠키에도 의존하므로 브라우저에서 쿠키를 사용하지 않는 경우 세션 상태도 작동하지 않습니다. 이 마지막 문제를 해결하는 방법은 "cookieless" 세션 상태를 사용하는 것입니다. 다음 절에서는 세션 상태에서 쿠키를 사용하는 방법에 대해 간략히 설명합니다.

쿠키 및 세션 상태

사용자가 사이트를 탐색하면 서버는 사용자가 방문하는 동안 지속되는 해당 사용자의 고유한 세션을 설정합니다. 각 세션에 대해 ASP.NET은 응용 프로그램에서 사용자 관련 정보를 저장할 수 있는 서버 기반 구조("세션 상태")를 유지 관리합니다. 자세한 내용은 Session State  를 참조하십시오.

ASP.NET은 각 사용자의 세션 ID를 추적할 수 있어야 사용자를 서버의 세션 상태 정보로 매핑할 수 있습니다. 기본적으로 ASP.NET은 비영구적인 쿠키를 사용하여 세션 상태를 저장합니다. 쿠키 읽기 절의 "쿠키 컬렉션 읽기"에 있는 예제 코드를 사용한 경우 쿠키 중에서 세션 상태 쿠키를 보았을 것입니다.

그러나 사용자가 브라우저에서 쿠키를 사용하지 않은 경우 세션 상태는 쿠키를 사용하여 세션 ID를 저장할 수 없으며 세션 상태가 작동하지 않습니다. 이것이 브라우저의 쿠키 사용 여부 확인에서 쿠키 테스트 후에 테스트 결과를 세션 상태에 저장하지 않는 것이 유용하다고 언급한 이유입니다. 쿠키가 없으면 세션 상태도 없습니다.

ASP.NET은 "cookieless" 세션 형식으로 해결 방법을 제공합니다. 세션 ID를 쿠키에 저장하지 않고 사이트의 페이지 URL에 저장하도록 응용 프로그램을 구성할 수 있습니다. ASP.NET은 세션 ID를 URL에 보관함으로써 이 ID를 브라우저에 저장하므로 사용자가 다른 페이지를 요청할 때 이 ID를 다시 가져올 수 있습니다.

Cookieless 세션에서 쿠키를 거부하는 브라우저의 문제를 해결하고 세션 상태로 작업할 수 있습니다. 응용 프로그램이 세션 상태에 의존할 경우 cookieless 세션을 사용하도록 구성할 수 있습니다. 그러나 일부 제한된 환경에서 사용자가 다른 사용자와 URL을 공유하는 경우(예: 사용자의 세션이 활성 상태인 동안 동료에게 URL을 전자 메일로 보내기) 두 사용자가 동일한 세션 공유를 끝내면 예상치 못한 결과가 발생할 수 있습니다.

Cookieless 세션을 사용하도록 응용 프로그램을 구성하는 방법에 대한 자세한 내용은 기술 자료 문서 INFO: ASP.NET 상태 관리 개요를 참조하십시오.


출처 : http://www.microsoft.com/korea/msdn/library/dv_vstechart/html/vbtchASPNETCookies101.asp

+ Recent posts