在Cookie的使用中,我們發現這樣一個問題:如果寫入Cookie的內容是中文(如使用者稱呼),用伺服器端程式(如ASP或PHP)讀出完全正確,但是用一般的javascript或VBScript的讀Cookie函數取出的卻是一堆亂碼。這是一個棘手的問題,因為在有些情況下,Cookie的內容需要在客戶機端用指令碼語言讀取。如果你寫入了中文,得到了一堆亂碼,是不是感覺很彆扭呢?解決這個問題,還要從Cookie的存取方式說起。
我們知道,寫入Cookie內容前需要進行escape(十六進位編碼),編碼時又是以位元組為單位的,這就是問題的關鍵所在:任何一個漢字都會被拆成兩個位元組分別編碼;而在讀Cookie時,unescape又以位元組單位解碼,因此最後每個漢字都變成了兩個位元組的亂碼。怎麼辦呢?ASP或PHP方式能夠正確讀出,應該是在unescape解碼後,又按照unicode編碼把其中的漢字拼了出來。如果這樣的話,能不能找到一種變通的方法解決這個問題呢?仔細研究後發現,只要在十六進位codec(編解碼)過程中能夠儲存漢字資訊就行了,因而我們需要再外包一層codec過程,方案如下:
1.在escape編碼前,把Cookie字串中的每個字元轉換為unicode碼的字串形式(用一特殊字元作為字串的分隔字元)。
2.在unescape解碼後,先把所有unicode字串提取出來,再用對應的函數轉換為原字元。
複製代碼 代碼如下:<SCRIPT LANGUAGE=javascript>
<!--
//編碼程式:
function CodeCookie(str)
{
var strRtn="";
for (var i=str.length-1;i>=0;i--)
{
strRtn+=str.charCodeAt(i);
if (i) strRtn+="a"; //用a作分隔字元
}
return strRtn;
}
//解碼程式:
function DecodeCookie(str)
{
var strArr;
var strRtn="";
strArr=str.split("a");
for (var i=strArr.length-1;i>=0;i--)
strRtn+=String.fromCharCode(eval(strArr[i]));
return strRtn;
}
//-->
</script>
VBScript版程式如下:
複製代碼 代碼如下:<SCRIPT LANGUAGE=vbscript>
<!--
"編碼程式:
function CodeCookie(str)
Dim i
Dim strRtn
for i=len(str) to 1 step -1
strRtn=strRtn & ascw(mid(str,i,1))
if (i<>1) then strRtn = strRtn & "a" "用a作分隔字元
next
CodeCookie=strRtn
end function
"解碼程式:
function DecodeCookie(str)
Dim i
Dim strArr,strRtn
strArr=Split(str,"a");
for i=UBound(strArr)-LBound(strArr) to 1 step -1
strRtn=strRtn & chrw(Val(strArr(i)))
next
DecodeCookie=strRtn
end function
-->
</script>
例如你要寫入的Cookie內容是"一頂abc",經過CodeCookie變為"99a98a97a-31029a26432a"(基於安全考慮,將字串反轉),再經過escape編碼後變為"99a98a97a%2D31029a26432a"(escape編碼將除字母和數字以外的字元轉換為十六進位%XX的形式),注意分隔字元不能選%,D和數字。當然,如果有類似密碼的重要訊息,還需要在加密上再強化一下。因為寫入Cookie的一般都是簡訊息,編碼後增加的一些位元組可忽略不計。下面的javascript讀寫Cookie函數中就加入了以上的中文支援。
function SetCookie(name,value,expires)
{
var exp=new Date();
exp.setTime(exp.getTime()+expires*60*1000);
documents.cookie=name+"="+escape(CodeCookie(value))+" ; expires="+exp.toGMTString()+" ; path=/";
}
function GetCookie (name)
{
var strArg=name+"=";
var nArgLen=strArg.length;
var nCookieLen=documents.cookie.length;
var nEnd;
var i=0;
var j;
while (i<nCookieLen)
{
j=i+nArgLen;
if (documents.cookie.substring(i,j)==strArg)
{
nEnd=documents.cookie.indexOf (";",j);
if (nEnd==-1) nEnd=documents.cookie.length;
return DecodeCookie(unescape(documents.cookie.substring(j,nEnd)));
}
i=documents.cookie.indexOf(" ",i)+1;
if (i==0) break;
}
return null;
}
如果用CGI程式寫入中文Cookie,用戶端讀取。如在ASP裡,可以先使用前述的編碼函數後,再用response寫入,例如:response.cookies("Name")=CodeCookie("張三")至此,中文Cookie的問題基本解決。