Javascript getCookie 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4003823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript getCookie functions
提问by FFish
I found two functions to get cookie data with Javascript, one on w3schools.comand one on quirksmode.org
I would like to know which one I should use?
我找到了两个使用 Javascript 获取 cookie 数据的函数,一个在w3schools.com 上,另一个在quirksmode.org
我想知道我应该使用哪一个?
For example I believe I read somewhere that there was a problem with some browsers splitting the ;
semicolon?
例如,我相信我在某处读到某些浏览器拆分;
分号存在问题?
w3schools:
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;
}
回答by Gumbo
The function from W3CSchool is wrong. It fails if there are multiple cookies that have the same suffix like:
W3CSchool 的函数是错误的。如果有多个具有相同后缀的 cookie,则它会失败,例如:
ffoo=bar; foo=baz
When you search for foo
it will return the value of ffooinstead of foo.
当您搜索时,foo
它将返回ffoo而不是foo的值。
Now here is what I would do: First of all, you need get to know the syntax of how cookies are transported. Netscape's original specification (there are only copies available like this one at haxx.se) uses semicolons to separate multiple cookies while each name/value pair has the following syntax:
现在我要做的是:首先,您需要了解 cookie 传输方式的语法。Netscape 的原始规范(在 haxx.se上只有这样的副本)使用分号来分隔多个 cookie,而每个名称/值对都具有以下语法:
NAME
=
VALUE
This string is a sequence of characters excluding semi-colon, comma and white space. If there is a need to place such data in the name or value, some encoding method such as URL style%XX
encoding is recommended, though no encoding is defined or required.
NAME
=
VALUE
这个字符串是一个不包括分号、逗号和空格的字符序列。如果需要在名称或值中放置此类数据,建议使用一些编码方法,例如 URL 样式%XX
编码,但不定义或不需要编码。
So splitting document.cookie
string at semi-colons or commas is a viable option.
因此,document.cookie
在分号或逗号处拆分字符串是一个可行的选择。
Besides that, RFC 2109does also specify that cookies are separated by either semi-colons or commas:
除此之外,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
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
Although both are allowed, commas are preferred as they are the default separator of list items in HTTP.
尽管两者都允许,但首选逗号,因为它们是 HTTP 中列表项的默认分隔符。
Note: For backward compatibility, the separator in the Cookie header is semi-colon (
;
) everywhere. A server should also accept comma (,
) as the separator between cookie-values for future compatibility.
注意:为了向后兼容,Cookie 标头中的分隔符
;
到处都是分号 ( )。服务器还应接受逗号 (,
) 作为 cookie 值之间的分隔符,以便将来兼容。
Furthermore, the name/value pair has some further restrictions as the VALUEcan also be a quoted string as specified in RFC 2616:
此外,名称/值对还有一些进一步的限制,因为VALUE也可以是RFC 2616 中指定的带引号的字符串:
attr = token value = token | quoted-string
attr = token value = token | quoted-string
So these two cookie versions need to be treated separately:
所以这两个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.;
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(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;
}
, ) {
var name = c_start = document.cookie.indexOf(c_name + "=");
,
value = .charAt(0) === '"'
? .substr(1, -1).replace(/\(.)/g, "")
: ;
cookies[name] = value;
});
}
return cookies;
}
function getCookie(name) {
return getCookies()[name];
}
回答by Craig Smedley
Yes, the W3Schools solution is incorrect.
是的,W3Schools 解决方案不正确。
For those that would like it, here is a simpler solutionthat works. It just prepends a space so the single call to indexOf() only returns the correct cookie.
对于那些想要它的人,这里有一个更简单的解决方案。它只是在前面加上一个空格,因此对 indexOf() 的单次调用只会返回正确的 cookie。
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;
}
回答by VoteyDisciple
This, from w3schools, is incorrectin that it may lead to getting the wrong cookie:
这来自 w3schools 是不正确的,因为它可能导致获取错误的 cookie:
##代码##If you go looking for a cookie named foo
(which we'll suppose is an existing cookie) then somewhere in document.cookie
will be the string foo=bar
.
如果你去寻找一个名为foo
(我们假设它是一个现有的 cookie)的 cookie,那么其中的某个地方document.cookie
将是 string foo=bar
。
However, there's no guarantee there won't alsobe the string xfoo=something
. Notice that this still contains the substring foo=
so the w3schools code will find it. And if the xfoo
cookie happens to be listed first, you'll get back the something
value (incorrectly!) instead of the expected bar
.
但是,也不能保证不会有同样是字符串xfoo=something
。请注意,这仍然包含子字符串,foo=
因此 w3schools 代码会找到它。如果xfoo
cookie 碰巧首先列出,您将返回something
值(错误地!)而不是预期的bar
.
Given the choice between two pieces of code, never go with the one that's fundamentally broken.
给定两段代码之间的选择,永远不要选择从根本上被破坏的那一段。
回答by B Factor
All of the code shown above is BROKEN. The two common problems are (1) the getcookie function may return the wrong value if one cookie name is a proper suffix of another cookie name; and (2) the setcookie function does not protect the cookie value, which means that if the cookie value includes (for example) a ";" then all the cookies are corrupted and cannot be parsed.
上面显示的所有代码都已损坏。两个常见的问题是 (1) 如果一个 cookie 名称是另一个 cookie 名称的正确后缀,则 getcookie 函数可能返回错误的值;(2) setcookie 函数不保护 cookie 值,这意味着如果 cookie 值包含(例如)一个“;” 那么所有的 cookie 都已损坏且无法解析。
TL;DR Use this well-written library instead: https://github.com/js-cookie/js-cookie
TL;DR 改用这个编写良好的库:https: //github.com/js-cookie/js-cookie
回答by Vincent Robert
Here is my version, it covers the edge case of quoted values.
这是我的版本,它涵盖了引用值的边缘情况。
##代码##