2011年9月6日 星期二

jQuery.cookie 如何讀取 Coldfusion cfcookie 的設定值

我們都知道在Coldfusion下設定cookie只需要使用 cfcookie tag,
例如我們設定一個cookie名稱叫cid,它的值為123456,有效期為1天:

<cfcookie name="cid" value="123456" expires="1">

如果用coldfusion來讀取這個只需要下:

<cfset idvar = cookie.cid>



#cookie.cid#

就可以簡單讀取。
但是某些情況下,若是用到了javascript來讀取這個值,就好像不是這麼一回事了,

目前我使用jQuery的Plugin:jQuery.cookie.js來讀取:

var cid = $.cookie("cid");

怎麼樣都讀取不到cfcookie設定的那個cid變數
於是乎我反過來測試,
先用jQuery設定再由cfcookie讀取(執行以前我會把瀏覽器中cookie紀錄全數清除)

$.cookie("cid","123456",{expires:1});

Coldfusion讀取

<cfset idvar = cookie.cid>

怪哉!居然可以正常取得值!?
於是乎,我寫了下面一段 cfml + javascript 在同一個頁面上來測試:

<body>
<cfcookie name="cid" value="123456" expires="1">
<script type="text/javascript">
var name="cid";
var value="123456";
var date = new Date();
date.setTime(date.getTime() + (1 * 24 * 60 * 60 * 1000));
var expires = '; expires=' + date.toUTCString();
document.cookie = [name, '=', encodeURIComponent(value), expires].join('');
</script>
</body>

把兩邊設定的cookie抓出來看(用FireFox的設定可以看到Cookie值),


耶?有兩個?大小寫不一樣?

原來cfcookie受到Coldfusion typeless的影響,寫入的cookie變數名稱是大寫,
讀取時也不受大小寫影響。
而jQuery受到javascript Case sensitive影響,所以會以使用者寫入變數大小寫為主,
而讀取時也會受到指定變數名稱大小寫影響,造成無法讀取。

因此,只要讓想辦法讓寫入/讀取時變數名稱大小寫相符就可以使用該cookie了,
所以我就直接修改了jQuery.cookie.js部份程式碼,讓它自動判斷cookie內的變數大小寫狀態:

jQuery.cookie.js裡面由一個 if 陳述式分成兩部份,上半部為設定cookie,下半部為取得cookie:

jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
    ...
    ...
    ...
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
    ...
    ...
    ...
        return cookieValue;
   }
}

在 if上下兩段陳述式結束前加入

jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
    ...
    ...
    ...

        //match the name for coldfusion
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                var aa=cookie.substring(0, name.length + 1);
                var bb=name+'=';
                if(aa.toLowerCase()==bb.toLowerCase()){
                    var pox=cookies[i].indexOf(aa,0);
                    bb=aa.substr(0,aa.length-1);
                    name=(pox<=0)?bb:cookies[i].substr(0,pox)+bb;
                    break;
                }
            }
        }

        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
    ...
    ...
    ...

            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                var aa=cookie.substring(0, name.length + 1).toLowerCase();
                var bb=(name + '=').toLowerCase();
                if (aa == bb) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }

        return cookieValue;
   }
}

這樣的話,使用者就不用管cookie變數是大寫還是小寫了。

另外,要特別注意的是javascript在建立cookie的時候,如果沒有特別指定路徑path,
則會自動以javascript執行的path為主,下面我將該測試頁放到/test/路徑下來執行,
結果cfcookie的內容不變,但是javascript的cookie卻產生如下:
卻出現了路徑??

然而Coldfusion的cfcookie則會以 root (/) 根路徑為主,因此若是cfcookie設定時,
如若不在root下的話,最好加上path已確保不會有問題,但是cfcookie設定path時,
必須連同domain一併設定,才能正常。

<cfcookie name="cid" value="123456" domain="#CGI.SERVER_NAME#" path="/test/" expires="1">

這一點,坦白說,adobe線上說明真的不清不楚,提示也少,難怪不好學。

※在產生cookie變數的時候,不同的path可以有相同的變數名稱,
但在cfcookie取得變數值的時候,卻永遠只能取得第一組同變數名稱的值,
因此在cookie變數設定上,還是盡量避免不同路徑相同的變數名,
要不然就只設定一組在root上的cookie就好。

-

0 個回應: