Soru Javascript getCookie işlevleri


Çerez verilerini Javascript ile almak için iki işlev buldum. w3schools.com ve bir tane quirksmode.org
Hangisini kullanmam gerektiğini bilmek ister misiniz?

Örneğin, bazı tarayıcıları bölme ile ilgili bir sorun olduğunu bir yerde okuduğuma inanıyorum. ; noktalı virgül?

W3Schools:

function getCookie(c_name) {
    if (document.cookie.length > 0) {
        c_start = document.cookie.indexOf(c_name + "=");
        if (c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = document.cookie.indexOf(";", c_start);
            if (c_end == -1) c_end = document.cookie.length;
            return unescape(document.cookie.substring(c_start, c_end));
        }
    }
    return "";
}

Alay modu:

function readCokie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
}

31
2017-10-23 11:53


Menşei


İkisi de aramaya gidiyor ; bildiğim kadarıyla, her zaman doğru olan çerezleri bölme karakterleri. - VoteyDisciple
getCookie işlev yanlıştır, adında bir çerez alırsanız ne olacağını düşünün ART= ve adında bir çerez var SMART= - Marco Demaio
w3schools bu yana getCookie işlevini değiştirdi (bkz. w3schools.com/js/js_cookies.asp), muhtemelen şimdi daha iyi çalışıyor. - pauloya
Şimdi aynı işlevi kullanıyorlar - sadece farklı isimler ve boşluklarla. - Kevin Busse


Cevaplar:


W3CSchool'un işlevi yanlış. Aynı son ekine sahip birden çok çerez varsa başarısız olur:

ffoo=bar; foo=baz

Ne zaman aradığınızı foo değerini döndürecek ffoo yerine foo.

Şimdi burada yapacağım şey: Öncelikle, çerezlerin nasıl taşındığının sözdizimini öğrenmeniz gerekiyor. Netscape’in orijinal özellikleri (yalnızca kopyaların bu bir haxx.se) her isim / değer çifti aşağıdaki sözdizimine sahipken birden çok çerez ayırmak için noktalı virgül kullanır:

ADI=DEĞER
  Bu dize, yarım kolon, virgül ve beyaz boşluk hariç karakter dizisidir. İsim veya değerde bu tür verilerin yerleştirilmesi gerekirse, URL stili gibi bazı kodlama yöntemleri %XX Hiçbir kodlama tanımlanmamış veya gerekli olsa da kodlama önerilir.

Yani bölme document.cookie Yarı-virgüller veya virgüllerde dize uygun bir seçenektir.

Bunun yanı sıra, RFC 2109 ayrıca, tanımlama bilgilerinin ya noktalı virgülle veya virgülle ayrılacağını da belirtir:

cookie          =       "Cookie:" cookie-version
                        1*((";" | ",") cookie-value)
cookie-value    =       NAME "=" VALUE [";" path] [";" domain]
cookie-version  =       "$Version" "=" value
NAME            =       attr
VALUE           =       value
path            =       "$Path" "=" value
domain          =       "$Domain" "=" value

Her ikisine de izin verilmesine rağmen, HTTP'deki liste öğelerinin varsayılan ayırıcısı oldukları için virgüller tercih edilir.

Not: Geriye dönük uyumluluk için, Cookie başlığındaki ayırıcı      yarı-kolondur (;) her yerde. Bir sunucu virgül de kabul etmeli (,)      gelecekteki uyumluluk için çerez değerleri arasındaki ayırıcı olarak.

Ayrıca, ad / değer çifti, bazı ek kısıtlamalara sahiptir. DEĞER ayrıca belirtildiği gibi bir alıntı dizesi olabilir RFC 2616:

attr        =     token
value       =     token | quoted-string

Yani bu iki çerez sürümü ayrı olarak ele alınmalıdır:

if (typeof String.prototype.trimLeft !== "function") {
    String.prototype.trimLeft = function() {
        return this.replace(/^\s+/, "");
    };
}
if (typeof String.prototype.trimRight !== "function") {
    String.prototype.trimRight = function() {
        return this.replace(/\s+$/, "");
    };
}
if (typeof Array.prototype.map !== "function") {
    Array.prototype.map = function(callback, thisArg) {
        for (var i=0, n=this.length, a=[]; i<n; i++) {
            if (i in this) a[i] = callback.call(thisArg, this[i]);
        }
        return a;
    };
}
function getCookies() {
    var c = document.cookie, v = 0, cookies = {};
    if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) {
        c = RegExp.$1;
        v = 1;
    }
    if (v === 0) {
        c.split(/[,;]/).map(function(cookie) {
            var parts = cookie.split(/=/, 2),
                name = decodeURIComponent(parts[0].trimLeft()),
                value = parts.length > 1 ? decodeURIComponent(parts[1].trimRight()) : null;
            cookies[name] = value;
        });
    } else {
        c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g).map(function($0, $1) {
            var name = $0,
                value = $1.charAt(0) === '"'
                          ? $1.substr(1, -1).replace(/\\(.)/g, "$1")
                          : $1;
            cookies[name] = value;
        });
    }
    return cookies;
}
function getCookie(name) {
    return getCookies()[name];
}

88
2017-10-23 12:44



Kurşun geçirmez kod için çok teşekkürler. - FFish
Hareket ederdim trimRight ve trimLeft dışında getCookie fonksiyonu: sadece bir kez ayarlamanız gerekir. - Tim Down
@ Aşağı Tutma: Evet, haklısınız. - Gumbo
$ Sürümünü kontrol ettiğiniz kodun parçası nedir? GetCookie'de fonksiyonlar gibi ilk kez görüyorum. Hala işe yarar mı? - Marco Demaio
Bu cevap, aşırı mühendisliğin temel bir örneğidir. Bu kodun tamamını neden dahil edersiniz, sorun, benzersiz olma olasılığı yüksek bir çerez adı oluşturarak kolayca çözülebilir. Örneğin. NAMESPACE_KEY - Anthony Martin


Evet, W3Schools çözümü yanlış.

İsteyenler için, işte burada daha basit bir çözüm bu işe yarıyor. Sadece bir alan açar, böylece indexOf () öğesine yapılan tek çağrı sadece doğru çerezleri döndürür.

function getCookie(c_name) {
    var c_value = " " + document.cookie;
    var c_start = c_value.indexOf(" " + c_name + "=");
    if (c_start == -1) {
        c_value = null;
    }
    else {
        c_start = c_value.indexOf("=", c_start) + 1;
        var c_end = c_value.indexOf(";", c_start);
        if (c_end == -1) {
            c_end = c_value.length;
        }
        c_value = unescape(c_value.substring(c_start,c_end));
    }
    return c_value;
}

8
2018-04-04 03:14





Bu, w3schools dan yanlış Bu yanlış kurabiye yol açabilir:

c_start = document.cookie.indexOf(c_name + "=");

Eğer adında bir kurabiye aramaya giderseniz foo (ki varsayalım ki var olan bir çerezdir) document.cookie dize olacak foo=bar.

Ancak, orada olmayacağına dair bir garanti yok. Ayrıca dize olmak xfoo=something. Bunun hala alt dizgi içerdiğine dikkat edin foo= böylece w3schools kodu onu bulacak. Ve eğer xfoo Çerez ilk önce listelenir, geri alırsınız something beklenen yerine değer (yanlış!) bar.

İki kod parçası arasında seçim yapıldığında, asla temelde kırılmış olanla gitmeyin.


6
2017-10-23 12:08





Yukarıda gösterilen kodun tamamı BROKEN. İki yaygın problem şunlardır: (1) bir çerez ismi başka bir çerez adının uygun bir eki ise, getcookie işlevi yanlış değer döndürebilir; ve (2) setcookie işlevi çerez değerini korumaz, yani çerez değeri (örneğin) bir ";" sonra tüm çerezler bozuk ve ayrıştırılamıyor.

TL; DR Bu iyi yazılmış kütüphaneyi kullanın: https://github.com/js-cookie/js-cookie


1
2017-12-31 19:06



Eşit işaretler içeren çift tırnaklı çerez değerleri için kabul edilen cevabı denedim ve işe yaramadı, ama js-cookie işi yaptı. - dlauzon