Javascript getCookie functions

Znalazłem dwie funkcje do pobierania danych cookie za pomocą Javascript, jedna na w3schools.com i jeden na quirksmode.org
Chciałbym wiedzieć, którego z nich powinienem użyć?

Na przykład czytałem gdzieś, że był problem z niektórymi przeglądarkami dzielącymi średnik ;?

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 "";
}

Quirksmode:

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;
}
Author: FFish, 2010-10-23

4 answers

Funkcja z W3CSchool jest błędna. To nie powiedzie się, jeśli istnieje wiele plików cookie, które mają ten sam przyrostek jak:

ffoo=bar; foo=baz

Podczas wyszukiwania foozwróci wartość ffoozamiast foo.

Oto, co chciałbym zrobić: przede wszystkim musisz poznać składnię, w jaki sposób pliki cookie są transportowane. Oryginalnej specyfikacji Netscape ' a (dostępne są tylko kopie jak ten na haxx.se ) używa średników do oddzielenia wielu pliki cookie, podczas gdy każda para nazwa / wartość ma następującą składnię:

NAZWA=WARTOŚĆ
Łańcuch ten jest sekwencją znaków z wyłączeniem dwukropków, przecinków i spacji. Jeśli istnieje potrzeba umieszczenia takich danych w nazwie lub wartości, zalecane jest kodowanie niektórych metod kodowania, takich jak kodowanie w stylu URL %XX, chociaż kodowanie nie jest zdefiniowane lub wymagane.

Więc dzielenie document.cookie ciągu na półkolonie lub przecinki jest żywotne opcja.

Poza tym, RFC 2109 określa również, że pliki cookie są oddzielone średnikami lub przecinkami:

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

Chociaż oba są dozwolone, preferowane są przecinki, ponieważ są domyślnym separatorem elementów listy w HTTP.

Uwaga: dla zgodności wstecznej separator w nagłówku pliku Cookie jest dwukropkiem (;) wszędzie. Serwer powinien również akceptować przecinek (,) jako separator pomiędzy wartościami plików cookie dla kompatybilność w przyszłości.

Ponadto para nazwa / wartość ma pewne dodatkowe ograniczenia, ponieważ wartość Może być również cytowanym ciągiem, jak określono w RFC 2616:

attr        =     token
value       =     token | quoted-string

Więc te dwie wersje plików cookie muszą być traktowane oddzielnie:

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];
}
 89
Author: Gumbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-09 17:49:40

Tak, rozwiązanie W3Schools jest niepoprawne .

Dla tych, którzy chcieliby, oto prostsze rozwiązanie , które działa. Po prostu dodaje spację, więc pojedyncze wywołanie indexOf () zwraca tylko poprawny plik cookie.

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
Author: Craig Smedley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-15 02:00:21

To, z w3schools, jest niepoprawne w związku z tym może to prowadzić do błędnego pliku cookie:

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

Jeśli szukasz pliku cookie o nazwie foo (który, jak przypuszczamy, jest istniejącym ciasteczkiem), to gdzieś w document.cookie będzie ciąg foo=bar.

Jednak nie ma gwarancji, że nie będzie również być ciągiem xfoo=something. Zauważ, że nadal zawiera podłańcuch foo=, więc kod w3schools go znajdzie. A jeśli plik cookie xfoo stanie się bądź na liście jako pierwszy, otrzymasz wartość something (niepoprawnie!) zamiast oczekiwanego bar.

Biorąc pod uwagę wybór pomiędzy dwoma kawałkami kodu, nigdy nie wybieraj tego, który jest zasadniczo zepsuty.

 6
Author: VoteyDisciple,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-23 12:13:32

Cały powyższy kod jest uszkodzony. Dwa typowe problemy to (1) funkcja getcookie może zwrócić niewłaściwą wartość, jeśli jedna nazwa pliku cookie jest odpowiednim przyrostkiem nazwy innego pliku cookie; oraz (2) funkcja setcookie nie chroni wartości pliku cookie, co oznacza, że jeśli wartość pliku cookie zawiera (na przykład)";", to wszystkie pliki cookie są uszkodzone i nie mogą być przetwarzane.

TL; DR Użyj tej dobrze napisanej biblioteki zamiast: https://github.com/js-cookie/js-cookie

 1
Author: B Factor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 19:06:07