JavaScript 中的 Cookie 是一种用于在浏览器和服务器之间传递数据的机制。它通常用于跟踪用户的会话信息,如登录状态、购物车内容等。
用法
设置Cookie
设置username='jack'
的cookie
document.cookie = 'username=jack';
封装下:
function setCookie(name, value) {
document.cookie = name + "=" + (value || "") + "; path=/";
}
setCookie('password', 123);
.
设置有过期时间的Cookie
可以通过设置cookie的expires属性来为其指定一个终止日期。
expires属性应该是一个GMT格式的日期字符串,表示cookie的过期时间。
当浏览器的时间达到这个过期时间时,cookie就会被自动删除。
例如,设置一个名为myCookie
的cookie,值为myValue
,7天后过期:
function setCookieWithExpiration(name, value, daysToExpire) {
var date = new Date();
date.setTime(date.getTime() + (daysToExpire * 24 * 60 * 60 * 1000)); // 设置过期时间为指定的天数之后
var expires = "; expires=" + date.toUTCString(); // 转换为GMT格式的字符串
document.cookie = name + "=" + (value || "") + expires + "; path=/"; // 设置cookie
}
// 使用示例
setCookieWithExpiration('myCookie', 'myValue', 7); //
.
读取Cookie
读取 Cookie 同样是通过 document.cookie 属性进行的。这个属性会返回一个包含所有 Cookie 的字符串,每个 Cookie 之间用分号和空格分隔。
假设cookie中存储的内容为:username =jack;password=123
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
getCookie(username) // jack
getCookie(password) // 123
.
删除Cookie
直接把expires
属性指定一个过去的时间,cookie就会被自动删除
-
删除一个 Cookie:
只需将其过期时间设置为一个过去的时间即可。例如:function deleteCookie(name) { document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; } deleteCookie('password');
-
删除所有Cookie:
可以编写一个函数来遍历当前所有的cookies,并为每一个设置过期时间为过去的时间。function deleteAllCookies() { var cookies = document.cookie.split(";"); for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i]; var eqPos = cookie.indexOf("="); var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; } } // 使用示例 deleteAllCookies();
.
判断是否存在指定的Cookie
function hasCookie(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 true;
}
return false;
}
hasCookie('password'); // 不存在返回false
hasCookie('username'); // 存在返回true
.
插件
-
jquery插件
地址:http://apps.bdimg.com/libs/jquery.cookie/1.4.1/jquery.cookie.js// 写入cookie $.cookie('name', 'value', { expires: 7 }); // 读取cookie var value = $.cookie('name'); // 删除cookie $.cookie('name', null);
-
webpack插件
npm install js-cookie --save
yarn add js-cookie
import Cookies from 'js-cookie'; // 设置cookie Cookies.set('name', 'value'); // 获取cookie const name = Cookies.get('name'); // 删除cookie Cookies.remove('name');
Set-Cookie 响应头
字段名 | 类别 | 描述 | 示例 |
---|---|---|---|
Name | 常见 | Cookie的名称 | UserID |
Value | 常见 | Cookie的值 | 123456 |
Expires | 有效期 | Cookie的过期日期/时间 | Expires=Wed, 21 Oct 2023 07:28:00 GMT |
Max-Age | 有效期 | 定义Cookie生命周期的秒数(如果设置,将覆盖Expires) | Max-Age=86400 (1天) |
Domain | 作用域 | 限制哪些域可以接收Cookie | Domain=example.com |
Path | 作用域 | 限制哪些路径下的页面可以接收Cookie | Path=/users |
Secure | 安全性 | 限制Cookie只能通过HTTPS传输 | Secure |
HttpOnly | 安全性 | 限制JavaScript访问(即无法通过document.cookie访问) | HttpOnly |
SameSite | 安全性 | 控制Cookie的跨站策略 | SameSite=Lax 或 SameSite=Strict 或 SameSite=None |
Set-Cookie 是一个 HTTP 响应头,用于向客户端(通常是浏览器)发送一个或多个 cookie。
当浏览器接收到带有 Set-Cookie 头的响应时,它会将这些 cookie 存储起来,并在后续的请求中将其发送回服务器。
1. 有效期(Expires、Max-Age)
在HTTP 响应头中可以通过设置
Set-Cookie
的Expires
和Max-Age
两个属性来设置Cookie 的有效期。
若 Cookie 过期,则这个 Cookie 会被删除,并不会发送给服务端。
Expires(GMT - 时间点)
Expires 是 HTTP 响应头中的一个字段,用于指定 Cookie 的过期日期和时间。
当浏览器收到带有 Expires 字段的 Set-Cookie 头部时,它会记住这个日期和时间,并在到达该日期后自动删除相应的 Cookie。
-
设置 Expires:
当服务器想要设置一个带有特定过期日期的 Cookie 时,它会在响应头中添加 Set-Cookie 字段,并附带 Expires 属性。
Expires 的值应该是一个格林威治标准时间(GMT)格式的日期和时间字符串,表示 Cookie 的过期时间。Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2030 07:28:00 GMT;
上例中:id 是 Cookie 的名称,值为
a3fWa
,而 Expires=Wed, 21 Oct 2023 07:28:00 GMT 表示这个 Cookie 将在 2030 年 10 月 21 日 07:28:00 GMT 过期。 -
Expires 的值:
- Expires 的值必须是一个完整的日期和时间,包括年、月、日、时、分、秒和时区。
- 如果 Expires 的日期早于当前日期,浏览器会立即删除这个 Cookie。
- 如果 Expires 的日期是未来的某个时间点,浏览器会在那个时间点删除这个 Cookie。
.
Max-Age(秒 - 时间段)
Max-Age 是一个 HTTP 头部指令,用于定义 Cookie 的生存时间,即 Cookie 在客户端保持有效的时间长度。单位是秒。
在客户端 JavaScript 中,你可以使用 document.cookie
来读取和写入 Cookie,但无法直接设置 Max-Age。
Max-Age 必须在服务器端的响应头中设置。然而,你可以通过 AJAX 请求或其他方式与服务器通信,从而间接地控制 Max-Age 的值。
当浏览器收到服务器返回的包含 Max-Age
的 Set-Cookie
头部时,它会根据这个值来决定何时过期并删除这个 Cookie。
-
设置 Max-Age:
当服务器想要设置一个带有特定生存时间的 Cookie 时,它会在响应头中添加 Set-Cookie 字段,并附带 Max-Age 属性。例如:Set-Cookie: id=a3fWa; Max-Age=604800;
在这个例子中,id 是 Cookie 的名称,a3fWa 是它的值,而 Max-Age=604800 表示这个 Cookie 将在 604,800 秒(即7天)后过期。
-
Max-Age 的值:
-
如果 Max-Age 为正数,浏览器会将其持久化到对应的 Cookie 文件中。
这意味着即使浏览器关闭或电脑重启,只要还在 Max-Age 指定的秒数之内,这个 Cookie 仍然是有效的。
例如:Max-Age=604800; 表示604800 秒内有效,与浏览器重启无关
-
如果 Max-Age 为负数,那么这个 Cookie 只会存在于当前浏览器会话中。
一旦浏览器窗口或标签页关闭,这个 Cookie 就会立即失效。
例如:Max-Age=-1; 浏览器重启后Cookie消失
-
如果 Max-Age 为 0,浏览器会立即删除这个 Cookie。
例如:Max-Age=0; 浏览器立即删除Cookie
-
.
优先级(Max-Age 高于 Expires )
- Expires 字段的值是基于特定的日期和时间,它可能会受到时钟偏差和时区设置的影响。是个时间点
- Max-Age字段的值只依赖于秒数,而不是具体的日期和时间。是个时间段
如果响应头中同时存在 Expires 和 Max-Age 属性,那么 Max-Age
将具有更高的优先级。
浏览器会优先使用 Max-Age 来确定 Cookie 的过期时间。
2. 作用域(Domain、Path)
在HTTP 响应头中可以通过设置
Set-Cookie
的Domain
和Path
两个属性来设置Cookie 的作用域。
Cookies的作用域是指Cookie在哪些URL或域名下是有效和可访问的。
Set-Cookie: name=value; Domain=.example.com; Path=/;
Domain(域)
Domain属性定义了哪些域名可以接收该Cookie。 默认情况下,Cookie只能被设置它的那个域名(不包括子域名)所访问。
例如,如果Cookie是由example.com
设置的,那么它只能被example.com
访问,而不能被subdomain.example.com
或其他任何域名访问。
然而,通过显式设置Domain属性,可以使Cookie对某个域及其所有子域都有效。
例如,如果Cookie的Domain被设置为.example.com
(注意前面的点),那么它将被example.com
、subdomain.example.com
、anothersubdomain.example.com
等所有子域所共享。
.
Path(路径)
Path属性定义了Cookie在哪个URL路径下是有效的。它指定了一个URL路径前缀,只有以这个前缀开头的URL才能访问该Cookie。
例如,如果Cookie的Path被设置为/myapp/
,那么只有example.com/myapp/
、example.com/myapp/somepage
等路径下的页面才能访问这个Cookie。
默认情况下,如果不设置Path属性,Cookie将只对设置它的那个页面(及其子路径)有效。
3. 安全性(HttpOnly、Secure、Samesite)
在HTTP响应头中可以通过设置
Set-Cookie
的HttpOnly
、Secure
、Samesite
三个属性来设置Cookie的安全性。
由于Cookies可以存储用户的敏感信息,因此它们的安全性至关重要。
HttpOnly
可以防止客户端脚本(如JavaScript)访问Cookie,即无法通过 document.cookie
访问,从而降低跨站脚本攻击(XSS) 的风险(不能直接防止CSRF攻击)。
禁止js访问Cookie: (防止跨站脚本攻击(XSS))
Set-Cookie: userID=JohnDoe; HttpOnly
.
Secure
确保Cookie只能通过HTTPS协议传输,这有助于防止Cookie在不安全的网络中被截获。
Cookie只能通过HTTPS协议传输:
Set-Cookie: userID=JohnDoe; Secure
.
Samesite
用来标明这个cookie是否是“同站cookie”。同站cookie只能在本域名中使用,不能作为第三方cookie, 限制第三方Cookie,从而帮助减少安全风险
设置为同站cookie,同站cookie只能在本域名中使用 。(防止跨站请求伪造攻击(CSRF))
SameSite 可以设置为 Strict
、Lax
或 None
:
-
Strict:
浏览器将只在同站点请求中发送 cookie(即,请求的目标 URL 与设置 cookie 的 URL 完全匹配)。Set-Cookie: userID=JohnDoe; SameSite=Strict
-
Lax :
浏览器将在同站点请求和顶级导航(即,通过链接跳转到的页面)中发送 cookie。Set-Cookie: userID=JohnDoe; SameSite=Lax
-
None:
浏览器将在所有请求中发送 cookie,但你必须同时使用 Secure 属性。Set-Cookie: userID=JohnDoe; SameSite=None; Secure
.
4. 服务端设置 Set-Cookie
在Java Servlet中,你可以使用Cookie类的构造函数和 setMaxAge()、setPath()、setSecure()、setHttpOnly()
方法来设置Cookie:
Cookie cookie = new Cookie("cookieName", "cookieValue");
cookie.setMaxAge(60 * 60 * 24); // 设置有效期为30天
cookie.setSecure(true); // 设置Secure属性:仅通过HTTPS传输
cookie.setHttpOnly(true); // 设置HttpOnly属性:防止JavaScript访问
cookie.setSameSite("Strict"); // 设置SameSite属性为Strict
response.addCookie(cookie); // 将Cookie添加到响应中
这样当服务器响应客户端请求时,就会在HTTP响应头中包含这些设置了属性的Cookie。
以百度的 Cookies 为例:
缺点
Cookie 的确是一种非常有用的技术,用于在客户端存储和跟踪用户会话信息。
然而,它们也有一些缺点和潜在的问题,以下是一些主要的缺点:
-
隐私问题:
Cookie 可以存储用户的个人信息,如果这些信息被不当处理或传输不安全,可能会泄露用户的隐私。
一些用户可能不喜欢网站在他们计算机上存储信息,这可能会引发信任问题。 -
安全问题:
如果 Cookie 没有正确设置 Secure 属性,它们可能会通过不安全的 HTTP 连接被传输,这可能导致会话劫持(session hijacking)等安全问题。
如果没有设置 HttpOnly 属性,客户端脚本(如 JavaScript)可以访问 Cookie,这增加了跨站脚本攻击(XSS)的风险。 -
大小限制:
每个 Cookie 的大小都有限制,通常是 4KB 左右,这限制了可以存储的信息量。
如果一个网站尝试设置过多的 Cookie,可能会因为浏览器限制而失败。 -
性能影响:
每次 HTTP 请求都会携带 Cookie,这可能会增加请求头的大小,从而影响网络传输的性能。
如果网站使用了大量的 Cookie,或者 Cookie 的内容很大,这可能会显著降低页面的加载速度。 -
不跨域:
Cookie 通常只能由设置它们的同一个域访问,这限制了跨域共享信息的能力。
虽然有一些技术(如 CORS with credentials)可以实现跨域 Cookie 共享,但这增加了复杂性和潜在的安全风险。 -
用户可删除或禁用:
用户可以随时删除他们计算机上的 Cookie,这可能导致网站功能失效或用户会话丢失。
一些用户可能会禁用 Cookie,这可能会影响网站的正常运行。 -
不适用于所有设备:
一些设备或浏览器可能不支持 Cookie,或者对 Cookie 的支持有限,这可能会影响网站在这些设备上的表现。
注意
-
大小限制:每个 Cookie 的大小通常限制在 4KB 以内,且浏览器对单个域名下的 Cookie 数量也有限制。
-
安全性:Cookie 中的敏感信息应该被加密,以防止被恶意用户窃取。同时,使用 HttpOnly 和 secure 属性可以增强 Cookie 的安全性。
-
隐私:过多的 Cookie 可能会影响用户的隐私体验,因此应该尽量减少不必要的 Cookie 使用。
如何发送一个带有cookie的HTTP请求
在JavaScript中,发送带有Cookie的HTTP请求通常是通过浏览器自动处理的。
默认情况下,如果浏览器的文档中存在 Cookie,并且这些 Cookie 对于请求的 URL 是有效的,那么浏览器会自动将这些Cookie附加到同源的Axios请求中,通常不需要额外的配置。
如果想从客户端手动设置 Cookie,或者在服务器端处理跨域请求时需要携带 Cookie,那么你需要确保满足以下几个条件:
-
跨域时服务器端设置:
对于跨域请求,服务器端需要设置正确的 CORS 策略,允许携带 Cookie。这通常涉及设置
Access-Control-Allow-Origin
、Access-Control-Allow-Credentials
等响应头。例如,在服务器端(以 Express.js 为例)你可能需要这样设置:
res.header('Access-Control-Allow-Origin', 'https://example.com'); // 允许请求的源 res.header('Access-Control-Allow-Credentials', true); // 允许携带凭证(即 Cookie)
-
跨域时客户端设置:
在 Axios 请求中,你需要设置withCredentials
选项为 true。只有需要处理跨域请求时才需要设置
withCredentials
。对于同源请求,浏览器默认会发送 Cookie。axios.defaults.withCredentials = true; // 全局设置 // 或者在单个请求中设置 axios.get('https://api.example.com/data', { withCredentials: true }) .then(response => { // 处理响应 }) .catch(error => { // 处理错误 });
-
手动设置请求头:
虽然不推荐这样做,因为这样做可能会绕过浏览器的安全策略,但在某些情况下,你可能需要手动设置请求头来包含Cookie。这通常不是跨域请求的做法,因为浏览器会阻止这样做以维护安全性。axios.get('https://api.example.com/data', { headers: { Cookie: 'your=cookie; another=cookie' // 这里的值应该是你希望发送的Cookie字符串 } }) .then(response => { // 处理响应 }) .catch(error => { // 处理错误 });
-
Cookie 的设置:
确保 Cookie 的SameSite
和Secure
属性设置正确,以避免由于浏览器的安全策略导致 Cookie 不被发送。-
Secure:确保Cookie只能通过HTTPS协议传输,这有助于防止Cookie在不安全的网络中被截获。
-
Samesite:用来标明这个cookie是否是“同站cookie”。同站cookie只能在本域名中使用,不能作为第三方cookie, 限制第三方Cookie,从而帮助减少安全风险
-
确保你理解浏览器如何处理Cookie以及CORS策略,因为这涉及到安全性问题。不要在不了解这些机制的情况下尝试绕过浏览器的安全限制。在大多数情况下,让浏览器自动处理Cookie是最简单和最安全的方法。