FrankKai.github.io
FrankKai.github.io copied to clipboard
前端cookie总结
看经验比我丰富的老哥的代码,惊觉自己对cookie的掌握程度,还是小学生的水平,所以开这个issue补充一下cookie知识点,以后在开发过程中总结到的好的实践也会记录在这里。
参考资料:https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
- cookie基础概念
- cookie使用实践
- 浏览器如何精确清除cookie
- 常见应用场景
- cookie是当前tab有效的还是所以tab有效的?
- 服务端如何既对token做处理又对cookie做处理?
- cookie与前端安全
cookie基础概念
读cookie
allCookies = document.cookie;
写cookie
;path=path
;domain=domain
path:1.若Path为 / ,那么无论是路径/foo还是子路径/foo/bar,从浏览器发到服务端的请求,在header中都会带上cookie头 2.必须是绝对路径 3.若不指定path,则为当前location的pathname domain:1.指出可以接收cookie的host。默认是location.host 2.若设置了Domain属性,那么它的子域名中也是包含这个cookie的 这两个属性定义了cookie的作用域,也就是说这个cookie是要发给谁的。
衍生面试题:聊一聊cookie的作用域?
;max-age=max-age-in-seconds
;expires=date-in-GMTString-format
这两个属性定义了cookie的过期时间。 expires和max-age都是设置过期时间的,规范定义规则如下:
The max-age directive takes priority over Expires, so if max-age is present in a response, the calculation is simply:
freshness_lifetime = max_age_value
Otherwise, if Expires is present in the response, the calculation is:
freshness_lifetime = expires_value - date_value
若真要问有什么区别:1.max-age精确到秒;而expires精确到毫秒 2.前端通过expires设置过期时间,服务端可以通过设置max-age来覆盖前端的过期时间
衍生面试题: 1.聊一聊max-age和expires的异同?见上文。 2.若max-age和expires同时设定了,哪一个会生效?The max-age directive takes priority over Expires
;secure
;samesite
设置secure的cookie仅在https之类的安全协议下可以传输。 samesite的设置,阻止浏览器发送跨站请求,有lax和strict两个值。strict会阻止所有跨站请求;lax仅仅允许在TOP LEVEL的GET请求中带cookie,可以阻止绝大多数CSRF攻击,子frame是不能发的。
衍生面试题: 1.TOP LEVEL是什么? TOP LEVEL指的就是window.top,也就是最顶级的window对象,例如在https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie 这个路径下,打开chrome devtools的控制台,我们看到的top指的就是developer.mozilla.org。
encodeURIComponent()
cookie值不允许包含分号,逗号,空格,但是可以使用encodeURIComponents编码。这个方法仅不编码A-Z a-z 0-9 - _ . ! ~ * ' ( )
。
__Secure-
__Host-
只能在安全的通道中包含cookie。__Host-则指明cookie仅在由浏览器指定的path下生效。
;httponly
;sameparty
httpOnly为true的cookie,是由服务端写入的,通过document.cookie是获取不到的,可以防御XSS攻击攻击。 sameparty可以将多个站点,看做第一方cookie,从而实现多站点域名共享。需要注意必须是secure并且samesite不为strict。例如.taogao.com,.tmall.com,.1688.com,组内成员彼此都作为第一方cookie。
cookie使用实践
- 前端cookie如何设置过期时间?
const d = new Date();
d.setTime(d.getTime() + 30*60*1000); // 设置过期时间为30分钟
const cookieKV = 'cookieKey=cookieValue';
const expires = `expires=${d.toGMTString()}`;// 由于cookie的过期时间类型为 ;expires=date-in-GMTString-format,所以需要用Date.toGMTString()转换成GMT类型
document.cookie = `${cookieKV};${expires}`; // 30分钟后此cookie失效,从cookie列表中删除
- 前端查询某个cookie已过期?
document.cookie.indexOf(`${name}=`); // 若返回-1则表示已过期
与第7题很类似。 还有很多其他写法。 3. 为什么需要设置cookie?
从前端的角度来说,因为有些时候需要从服务端获取一个token,signa之类的凭证或者数字签名,cookie的设定,可以使得在凭证有效期内,不用频繁向服务端发送获取token的请求,直接从浏览器本地获取cookie即可完成之后的请求。 从服务端的角度来说,由于前端设置了cookie过期时间,有效期内不用访问服务端获取凭证,从而减轻服务端服务的压力。
- 如何获取一个指定名字的cookie?
getCookieValueByName(cookieName){
const cookieValue = document.cookie.replace(/(?:(?:^|.*;\s*)name\s*\=\s*([^;]*).*$)|^.*$/, "$1");
return cookieValue;
}
- 如何设置一个只用一次的cookie?
function doOnce() {
if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
alert("Do something here!");
document.cookie = "doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT"; // Sat Jan 01 10000 07:59:59 GMT+0800 (中国标准时间) 10000年1月1日
}
}
- 重置一个cookie?
function resetOnce() {
document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
}
7.确定一个cookie是否存在或者有效?
checkCookieExsitence(cookieName){
if (document.cookie.split(';').filter((item) => item.trim().startsWith(`${cookieName}=`)).length) {
return true;
}
return false;
}
与第2题很类似。
8.确定一个cookie的值是否为指定值?
checkCookieExsitence(cookieName, cookieValue){
if (document.cookie.split(';').filter((item) => item.includes(`${cookieName}=${cookieValue}`)).length) {
return true;
}
return false;
}
浏览器如何精确清除cookie
1.网站设置→Cookie→查看所有Cookie和网站数据
找到需要删除的网站并删除Cookie即可。
2.点击浏览器url左边的不安全或锁子
常见应用场景
cookie是当前tab有效的还是所以tab有效的?
cookie是通过domain指定作用范围的。 若是服务端,可以指定domain,若是跨系统cookie,一般是一级域名;若指定系统,可以指定二级,三级域名。 若是前端,一般是设置在document.cookie上,在当前域名设置。
服务端如何既对token做处理又对cookie做处理?
const certificate = token || cookie
优先使用token。
cookie与前端安全
敏感数据的cookie(httpOnly为true)通过服务端写入。
为了避免XSS和CSRF攻击,包含敏感数据的cookie通过服务端写入,此时httpOnly属性为true,浏览器通过document.cookie 这个api获取不到,是一种安全防范措施。