Javascript getCookie функции - PullRequest
       6

Javascript getCookie функции

31 голосов
/ 23 октября 2010

Я нашел две функции для получения данных cookie с помощью Javascript, одну на w3schools.com и одну на quirksmode.org Я хотел бы знать, какой из них мне следует использовать?

Например, мне кажется, я где-то читал, что в некоторых браузерах есть проблема с разделением точки с запятой ;?

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

Причудливый режим:

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

Ответы [ 5 ]

91 голосов
/ 23 октября 2010

Функция W3CSchool неверна. Сбой, если существует несколько файлов cookie с одинаковым суффиксом, например:

ffoo=bar; foo=baz

При поиске foo возвращается значение ffoo вместо foo .

Теперь вот что я хотел бы сделать: во-первых, вам нужно узнать синтаксис, как транспортируются куки. Исходная спецификация Netscape (есть только копии, доступные как , эта на haxx.se ) использует точки с запятой для разделения нескольких файлов cookie, в то время как каждая пара имя / значение имеет следующий синтаксис:

ИМЯ = VALUE
Эта строка представляет собой последовательность символов, исключая точку с запятой, запятую и пробел. Если необходимо поместить такие данные в имя или значение, рекомендуется использовать какой-либо метод кодирования, например кодирование в стиле URL %XX, хотя кодировка не определяется или не требуется.

Таким образом, разделение строки document.cookie на точки с запятой или запятую является приемлемым вариантом.

Кроме того, RFC 2109 также указывает, что файлы cookie разделяются либо точками с запятой, либо запятыми:

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

Хотя оба допускаются, предпочтительны запятые, поскольку они являются разделителем по умолчанию для элементов списка в HTTP.

Примечание: для обратной совместимости, разделитель в заголовке Cookie это точка с запятой (;) везде. Сервер также должен принимать запятую (,) в качестве разделителя между значениями cookie для будущей совместимости.

Более того, пара имя / значение имеет некоторые дополнительные ограничения, поскольку VALUE также может быть строкой в ​​кавычках, как указано в RFC 2616 :

attr        =     token
value       =     token | quoted-string

Таким образом, эти две версии файлов cookie должны рассматриваться отдельно:

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];
}
10 голосов
/ 04 апреля 2014

Да, решение W3Schools является неверным .

Для тех, кто хотел бы, вот простое решение , которое работает.Он просто добавляет пробел, поэтому единственный вызов indexOf () возвращает только правильный файл 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;
}
6 голосов
/ 23 октября 2010

Это от w3schools неверно в том смысле, что это может привести к получению неправильного файла cookie:

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

Если вы ищете файл cookie с именемfoo (который мы предполагаем, что это существующий файл cookie), тогда где-то в document.cookie будет строка foo=bar.

Однако, нет никакой гарантии, что также не будет будет строкой xfoo=something.Обратите внимание, что он по-прежнему содержит подстроку foo=, поэтому код w3schools найдет ее.И если файл cookie xfoo окажется первым в списке, вы получите значение something (неправильно!) Вместо ожидаемого bar.

Учитывая выбор между двумя частями кода,никогда не подходи к тому, кто в корне сломлен.

2 голосов
/ 31 декабря 2017

Весь код, показанный выше, BROKEN.Двумя распространенными проблемами являются: (1) функция getcookie может возвращать неправильное значение, если одно имя файла cookie является правильным суффиксом другого имени файла cookie;и (2) функция setcookie не защищает значение cookie, что означает, что если значение cookie включает (например) «;»тогда все файлы cookie повреждены и не могут быть проанализированы.

TL; DR Вместо этого используйте эту хорошо написанную библиотеку: https://github.com/js-cookie/js-cookie

0 голосов
/ 06 апреля 2019

Вот моя версия, она охватывает крайний край указанных значений.

function getCookies() {
  const REGEXP = /([\w\.]+)\s*=\s*(?:"((?:\\"|[^"])*)"|(.*?))\s*(?:[;,]|$)/g;
  let cookies = {};
  let match;
  while( (match = REGEXP.exec(document.cookie)) !== null ) {
    let value = match[2] || match[3];
    cookies[match[1]] = decodeURIComponent(value);
  }
  return cookies;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...