쿠키는 서버와 클라이언트 사이에 정보를 주고 받을 수 있는 통로인 동시에, 서버가 사용할 수 있는 유일한 로컬시스템(클라이언트) 자원입니다. 이러한 쿠키를 이용하면 방문자에게 좀 더 친밀한(?) 서비스를 제공할 수 있는 웹사이트를 구성할 수 있습니다.
하지만 쿠키가 로컬시스템에 저장된다는 것 때문에 혹시 나의 정보가 나도 모르게 외부로 유출되지 않는가 하는 걱정을 하게 만드는 것도 쿠키입니다.
여기서는 쿠키가 매우 유용한 도구라는 긍정적인 면에서 쿠키정보를 다루기 위한 클래스를 작성해 보려 합니다. 이 클래스는 세셔너에 포함된 세셔너핸들러 쿠키용과 비교해 볼 때 유사한 부분이 많이 있습니다. 그러나 쿠키만을 위해 제작되었기 때문에 소스 분석하기에는(이해하기에는) 훨씬 수월할 것입니다. 이 클래스는 쿠키를 요리하는 도구의 역할을 하기 때문에 이름을 쿠커(cooker)라고 정했습니다.
쿠키(cooker - class.cooker.php)를 이용하는 것이 보안상 여러가지 문제를 가지고 있음에도 불구하고 제가 쿠커를 작성하는 것은 쿠키가 세션과 같은 다른 방법보다는 이해하기가 쉽고 웹문서를 작성하기가 편하고 단순하다는 것입니다. 또한 서버자원이 아닌 방문자의 로컬시스템 하드디스크에 쿠키정보를 저장하게 되어 많은 방문자가 동시에 접속하는 웹사이트에서는 많은 장점을 가지게 됩니다. 그리고 보안에 조금만 주의를 기울인다면 아주 민감한 정보가 아닌 이상은 적용하는데 별 무리가 없다는 이유도 있습니다. 제 자신과 여러분에게도 한번쯤은 쿠키 사용법을 습득할 수 있는 기회가 될 수도 있겠지요.
쿠커란?
쿠키를 직접 관리해주는 클래스입니다. 클라이언트에서 날라온 쿠키값을 디코딩(암호 해독 과정 포함)하여 얻은 정보를 이용해 쿠키변수를 설정합니다. 이 과정에서 쿠키가 담고 있는 현재 상태를 얻을 수 있습니다. 새로운 쿠키를 생성할 때는 쿠키변수 정보를 인코딩(암호화 과정 포함)하여 이 정보를 클라이언트로 보내어 쿠키파일에 저장할 수 있도록 합니다. 인코딩 과정에서 쿠키변수 정보와 함께 클라이언트 IP 및 현재 시간을 함께 담아 보내게 되며 이러한 정보는 다음 페이지에서 쿠키를 디코딩하는 과정에서 추출되어 적절히 이용하게 됩니다. 클라이언트 IP는 보안을 고려할 때 필요한 정보이고 현재 시간은 쿠키의 유효기간을 결정하기 위한 정보로 사용됩니다.
< 쿠커의 역할 >
쿠키의 유효기간
쿠키의 유효기간은 우선 params() 메소드로 설정할 수 있습니다. params()에 의해 쿠키 생성할 때 설정된 유효기간은 웹브라우저에 의해 관리됩니다. params() 메소드에서 lifetime의 기본값은 0입니다. 따라서 브라우저가 살아있는 동안만 쿠키가 존재합니다. 브라우저를 종료하는 즉시 쿠키 정보도 같이 사라집니다.
서버에서 관리되는 쿠키의 유효기간이 별도로 존재합니다. 브라우저에서 관리되는 lifetime과 독립적으로 서버에서는 쿠키 생성 후 31536001초(1년)가 지나면 쿠커가 생성한 쿠키를 삭제하도록 되어있습니다. 이 값은 gc_maxlifetime() 메소드로 변경될 수 있습니다.
gc_maxlifetime() 함수로 유효기간을 설정하는 것은 쿠키를 처음 생성할 때 한번만 수행하면 됩니다. 따라서 여러페이지에 걸쳐 쿠커를 사용할 때는 처음 진입하는 페이지에서만 이 함수로 유효기간을 설정하면 됩니다. 다른 페이지에서는 이 함수를 사용하지 않더라도 이미 유효기간에 대한 정보가 쿠키 내에 포함되어 있으므로 자동으로 수행할 수 있습니다.
제공되는 메소드
메소드 버전 기능
start 0.0.1 쿠키파일로부터 쿠키정보를 전달받아 쿠키변수 설정
params 0.0.1 쿠키 설정 매개변수 획득/설정
gc_maxlifetime 0.0.2 서버상에서 확인하는 쿠키의 생존시간 획득/설정
name 0.0.1 쿠키파일에 저장될 쿠키명 획득/설정
get 0.0.1 쿠키변수값 획득
set 0.0.1 쿠키변수 등록 및 값 설정
isset2 0.0.2 쿠키변수 존재여부 확인
unset2 0.0.1 쿠키변수 삭제
write 0.0.1 쿠키변수에 기록된 쿠키정보를 쿠키파일에 저장
delete 0.0.1 쿠키변수 삭제, 쿠키파일의 쿠키삭제
메소드 사용법
int start(void)
클라이언트에서 전달된 쿠키를 받아 그 정보를 디코딩한 후 방문자 IP, 쿠키에 마지막으로 접근한 시간, 쿠키변수를 설정합니다. 그리고 쿠키와 PHP에 의해 자동으로 만들어지는 $HTTP_COOKIE_VARS["쿠키명"] 및 해당 전역변수를 삭제합니다. 따라서 이들 전역변수에 의해 쿠키값에 접근할 수 없습니다. 쿠키명은 디폴트로 "PHP_AUTH_DATA"로 지정되어 있습니다.
방문자 IP, 쿠키에 마지막으로 접근한 시간, 쿠키변수 정보를 통해 쿠키의 현재 상태를 파악해 그 값을 되돌려 줍니다. 마지막으로 현재 시간을 기준으로 쿠키파일의 쿠키를 업데이트합니다.
< start() 함수의 동작 >
반환되는 상태값을 보면 다음과 같습니다.
상태값 설명
0 등록된 쿠키변수가 존재함(정상적인 상태)
1 초기 상태(이전에 쿠키가 생성된 적이 없거나 브라우저가 쿠키를 받아들이지 않음)
2 쿠키가 만료되었음, 따라서 등록된 모든 쿠키변수가 삭제되었음
3 등록된 쿠키변수가 없음
4 앞서 쿠키를 생성한 방문자 IP와 현재 방문자 IP가 다름(이상한 사람임)
[code php;gutter:false] <?php

require "./cooker/class.cooker.php"; // 쿠키정보 클래스

$cooker = new Cooker;

$cooker->params(3600);
$status = $cooker->start();

switch ($status) {
case 0:
echo "이전 페이지에서 쿠키변수를 등록하셨군요.\n"";
echo "\n";
echo "USERID=".$cooker->get("USERID")."\n"";
echo "DATA=".$cooker->get("DATA")."\n"";
$cooker->delete();
echo "쿠키변수 및 쿠키파일의 쿠커정보를 지웠습니다.\n"";
echo "USERID=".$cooker->get("USERID")."\n"";
echo "DATA=".$cooker->get("DATA")."\n"";
break;
case 1:
$data = "처음으로 구원진 쿠키";
$cooker->set("USERID", "hwooky");
$cooker->set("DATA", $data);
$cooker->write();
echo "이전에 쿠키가 생성된 적이 없거나"
." 브라우저가 쿠키를 받아들이지 않습니다.\n"";
echo "\n";
echo "USERID=hwooky\n"";
echo "DATA=$data\n"";
echo "새로운 쿠키를 구웠습니다.\n"";
break;
case 2:
$data = "쿠키가 만료되었습니다.";
break;
case 3:
echo "등록된 쿠키변수가 없습니다.\n"";
break;
case 4:
echo "어떻게 들어오셨어요???\n"";
break;
}

echo "<A href=$PHP_SELF?id=$id>다시실행</A>";

?> [/code]
쿠커 내부에서 기본으로 설정된 유효기간은 24분(1440초)입니다. 이것은 세션함수에서의 유효기간 기본값과 같습니다.
void params(int lifetime [, string path [, string domain]])
PHP4 세션함수에서 session_set_cookie_params() 함수와 같이 쿠키를 생성할 때 필요한 유효기간, 유효경로, 유효도메인을 설정하는데 사용되는 함수입니다. 이 함수는 반드시 start() 함수보다 앞서 수행하여야 합니다. 각 매개변수에 대한 자세한 설명을 앞장("쿠키 규격") 및 PHP4 메뉴얼 세션함수를 참조바랍니다.
[code php;gutter:false] $cooker->params(3600, "/phpclass/exam/cooker/", ".phpclass.com"); [/code]
첫번째 매개변수 lifetime는 쿠키가 생존하는 시간을 초로 나타냅니다. 3600초라고 지정하면 쿠키를 생성한 후 1시간이 지나면 쿠키는 더 이상 유효하지 않습니다. 이 값의 디폴트 값은 0이며 이 경우의 쿠키는 사용자가 브라우저를 종료할 때까지만 존재합니다.
두번째 매개변수 path는 유효경로를 지정합니다. 특정 디렉토리에서만 이용할 필요가 있는 쿠키를 생성할 때 유효경로를 지정합니다. 위와 같이 "/phpclass/exam/cooker/"라고 지정하면 "http://www.phpclass.com/phpclass/exam/cooker/"의 디렉토리 및 그 하위디렉토리에 있는 웹문서만 사용할 수 있는 쿠키를 생성합니다. 다른 곳에 있는 웹문서는 이 쿠키를 받을 수 없습니다. 디폴트 값은 "/"이며 이 경우의 쿠키는 서버의 모든 디렉토리에서 유효합니다.
세번째 매개변수 domain은 쿠키의 유효도메인을 지정합니다. 위와 같이 ".phpclass.com"이라고 지정하면 www.phpclass.com, ftp.phpclass.com 등 도메인의 뒷부분이 일치하는 웹서버로만 쿠키가 전달됩니다. 디폴트 값은 ""이며 이 경우의 쿠키는 쿠키를 생성한 서버의 도메인으로 자동 지정됩니다.
array params()
PHP4 세션함수에서 session_get_cookie_params() 함수와 같은 역할을 수행합니다. 즉 쿠키를 생성할 때 필요한 유효기간, 유효경로, 유효도메인의 현재 설정값을 되돌려 줍니다.
[code php;gutter:false] $params = $cooker->params();
echo "유효기간=".$params["lifetime"]."\n""
echo "유효경로=".$params["path"]."\n""
echo "유효도메인=".$params["domain"]."\n"" [/code]
void gc_maxlifetime(int lifetime), int gc_maxlifetime(void)
위에 있는 params() 함수가 클라이언트에 생성하게 되는 쿠키의 유효기간을 설정하는 것이라면 gc_maxlifetime() 함수는 서버에서 쿠키의 유효기간을 확인할 수 있도록 그 시간을 설정하거나 획득하기 위한 함수입니다.
[code php;gutter:false] $cooker = new Cooker;
$cooker->params(0); //클라이언트에서의 쿠키지속시간
$cooker->gc_maxlifetime(1440); //서버에서의 쿠키지속시간(초단위/24분)
$cooker->start(); [/code]
위와 같은 경우 params()에서 lifetime을 0으로 설정하였기 때문에 클라이언트에서의 쿠키지속시간은 브라우저가 살아있는 한 계속 쿠키는 존재합니다. 그러나 쿠키가 생성된 후 24분이 지나면 서버에서 gc_maxlifetime(1440)에 의해 쿠키정보를 임의로 삭제하게 됩니다. 이러한 기능은 시간에 의한 자동로그아웃을 구현할 때 유용하게 사용될 수 있을 것입니다.
params()와 gc_maxlifetime() 함수에서 설정할 때는 모두 start() 함수 전에 수행하여야 합니다.
string name([string newname])
쿠커에서 사용되는 쿠키명(cookie name)을 얻거나 새로운 쿠키명으로 설정할 때 사용할 수 있습니다. 새로운 쿠키명을 설정할 때는 반드시 start() 함수보다 앞서 수행하여야 합니다. 쿠커는 기본적으로 쿠키명을 "PHP_AUTH_DATA"로 설정되어 있습니다. 보안을 위해 주기적으로 변경해주는 것이 바람직합니다.
[code php;gutter:false] $cooker = new Cooker;
$cooker->name("NEW_COOKIE_NAME");
$cooker->start();
.
.
. [/code]
array get(void)
등록된 모든 쿠키변수에 대한 정보를 되돌려줍니다. 정확한 정보를 얻기 위해서는 start() 함수를 먼저 수행하여야 합니다.
[code php;gutter:false] $list = $cooker->get();
if (is_array($list))
while(list($name,$value)=each($list))
echo "\$list[$name]=$value\n""; [/code]
string get(string name)
쿠키변수명을 입력 매개변수로 지정하면 해당 쿠키변수명에 대한 값을 되돌려 줍니다.
[code php;gutter:false] $userid = $cooker->get("USERID"); [/code]
void set(string name [, string value])
쿠키변수를 등록시켜주며 동시에 그 값을 설정합니다. 값을 지정하지 않으면 널문자열로 초기화합니다.
[code php;gutter:false] $cooker->set("USERID", "hwooky"); [/code]
bool isset2(string name)
등록된 쿠키변수가 존재하는지 확인합니다. 존재하면 true, 아니면 false를 반환합니다. 쿠키변수의 값이 null이더라도 존재한다면 true를 반환합니다.
[code php;gutter:false] if ($cooker->isset2("USERID"))
echo "쿠키변수 USERID가 존재하네요.\n""; [/code]
void unset2([string name])
등록된 쿠키변수를 삭제합니다. 입력 매개변수를 지정하지 않으면 모든 쿠키변수를 삭제합니다.
[code php;gutter:false] $cooker->unset2("USERID"); [/code]
쿠키변수를 삭제해 주는 함수의 함수명은 unset2입니다. 메소드명을 unset으로하여 함수를 정의하면 에러(Parse error)가 발생하여 할 수 없이 unset2로 명명하였습니다. 클래스 내에서 정의된 메소드명이라 내장함수 unset와 전혀 관련이 없는데도 에러가 나는 것을 보면 PHP의 버그가 아니면 unset() 함수가 다른 함수와 달리 PHP 내에서 특수하게 처리되는 것 같습니다. 이와같이 메소드명으로 사용할 수 없는 함수명으로는 unset 외에도 empty, isset 입니다. 모두 변수 처리 관련 함수들입니다.
void write(void)
등록된 쿠키변수와 기타 쿠키파일에 저장할 정보를 인코딩(암호화 포함)하여 쿠키파일에 저장합니다. start() 함수를 먼저 수행하여야 하며, 또한 내부적으로 PHP header() 함수를 사용하기 때문에 브라우저로 출력하는 문자가 발생하기 전에 수행하여야 합니다.
[code php;gutter:false] $cooker->write(); [/code]
void delete()
쿠키변수를 모두 삭제한 후 쿠키파일에서 쿠커가 사용하는 쿠키를 삭제합니다. write() 함수와는 달리 응답헤더 정보와 관계없이 수행합니다. 왜냐하면 쿠키를 삭제하기 위해 PHP header() 함수를 사용하지 않으며 자바스크립트의 document.cookie 객체를 이용합니다. 로그아웃과 같은 기능을 수행할 때 요긴하게 사용될 수 있을 것입니다. 없어도 로그아웃할 수는 있겠지만 보다 편하게 하기 위해 작성되었습니다.
[code php;gutter:false] $cookie->delete(); [/code]
데이터 암호화 클래스(class.crypto.php)
보안에 취약한 쿠키의 단점을 다소나마 보완하기 위해 쿠키값을 암호화하는데 활용할 수 있는 클래스입니다. 이 클래스는 제가 작성한 것이 아니며 hansanderson 라는 분이 작성하여 공개한 것을 포함시켰을 뿐입니다. 쿠키를 아무리 암호화한다고 해도 그 알고리즘이 노출된다면 본래의 목적이 반감될 수 밖에 없다는 것을 인식하시고 이 부분은 직접 작성할 것을 고려해 보시는 것이 좋을 듯합니다. 따라서 이 클래스는 참고용으로 첨부되어 있을 뿐입니다. 이 클래스에서 정의된 메소드는 쿠커(class.cooker.php)에서 사용하게 됩니다. 그러나 실제로 쿠커 내용을 보면 아시겠지만 데이터 암호화 클래스에 있는 메소드를 전혀 이용하지 않고 있습니다. 동일한 메소드를 쿠커 내에서 더미함수로 정의하여 사용하고 있습니다. 따라서 현재의 쿠커를 이용하더라도 쿠키의 암호화는 수행되지 않습니다. 이것은 여러분의 몪으로 남겨 놓겠습니다. 아래는 데이터 암호화 클래스(class.crypto.php)를 공개한 분에 대한 개인신상입니다.
AUTHOR hansanderson
HOME www.hansanderson.com/php/crypto/
EMAIL corporation@hansanderson.com
쿠커를 이용한 실험 예제
메뉴 "회원인증정보 >> 장바구니 클래스"에 있는 예제를 실험 대상으로 하였습니다. 자세한 것은 "장바구니 클래스"를 참조바랍니다.

Posted by 방글24