遇到的cookie的坑
前段时间做项目(技术栈vue-cli + element),本地联调的时候遇到了一个关于cookie的坎,之前和后端沟通的是项目初始化接口的时候,后台会在响应头里面设置一个cookie,前端不需要做任何事情,后续的每次请求浏览器都会自动把后端返回的cookie添加到响应头里面给后端,但是推到环境上又是没有问题的
但是在发送接口的时候后端一直获取不到cookie导致后端校验一直通不过,没法进行联调,然后笔者想通过document.cookie去手动设置,却没有办法通过js代码获取,然后就一顿查找资料
后来发现是后端在设置cookie的时候把path设置到了init接口上,如果修改的化,后端需要改动有点多,所以商量让前端来解决这件事情
附上解决方法,修改完重启生效
两步走
- 第一步
axios请求设置
axios.default.withCredentials = true - 第二步
// vue.config.js
module.export = {
devServer: {
......
proxy: { //配置自动启动浏览器
"/api": {
target: "https://bot-test.dingtax.cn",
changeOrigin: true,
// ws: true,//websocket支持
secure: false,
pathRewrite: {
'^/api': '/' //代理的路径
},
onProxyRes(proxyRes, req, res) {
if(proxyRes.headers['set-cookie']) {
proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map(v => {
// /coss/app是后端服务设置的上下文跟, 由于是本地所以需要添加一个代理/api(于proxy端口的代理是一样的)
return v.replace('/coss/app', '/api/coss/app')
})
}
}
},
}
}
}
简单介绍一下cookie
什么是cookie
由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的。Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用。比如判断用户是否是第一次访问网站。目前最新的规范是RFC 6265,它是一个由浏览器服务器共同协作实现的规范。
Cookie的处理分为:
服务器像客户端发送cookie
浏览器将cookie保存
之后每次http请求浏览器都会将cookie发送给服务器端
cookie是如何工作的
首先必须明确一点,存储cookie是浏览器提供的功能。cookie 其实是存储在浏览器中的纯文本,浏览器的安装目录下会专门有一个 cookie 文件夹来存放各个域下设置的cookie。
当网页要发http请求时,浏览器会先检查是否有相应的cookie,有则自动添加在request header中的cookie字段中。这些是浏览器自动帮我们做的,而且每一次http请求浏览器都会自动帮我们做。这个特点很重要,因为这关系到“什么样的数据适合存储在cookie中”。
存储在cookie中的数据,每次都会被浏览器自动放在http请求中,如果这些数据并不是每个请求都需要发给服务端的数据,浏览器这设置自动处理无疑增加了网络开销;但如果这些数据是每个请求都需要发给服务端的数据(比如身份认证信息),浏览器这设置自动处理就大大免去了重复添加操作。所以对于那设置“每次请求都要携带的信息(最典型的就是身份认证信息)”就特别适合放在cookie中,其他类型的数据就不适合了。
如何设置cookie
cookie的属性选项
"key=value; expires=Thu, 25 Feb 2020 16:18:00 GMT; domain=.baidu.com; path=/; secure; HttpOnly"
- key:一个唯一确定的cookie名称。通常来讲cookie的名称是不区分大小写的。
- value:存储在cookie中的字符串值。最好为cookie的key和value进行url编码
- domain:cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:www.baidu.com),也可以不包含它(如:.baidu.com,则对于baidu.com的所有子域都有效)。如果不设置默认值是该cookie的网页所在的域名
- path: 表示这个cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送cookie。如果不设置默认值是该cookie的网页所在的目录。
domain和path两个选项共同决定了cookie何时被浏览器自动添加到请求头部中发送出去,你有没有遇到发生跨域xhr请求时,即使请求URL的域名和路径都满足 cookie 的 domain 和 path,默认情况下cookie也不会自动被添加到请求头部中?
造成这个问题的原因是:在CORS标准中做了规定,默认情况下,浏览器在发送跨域请求时,不能发送任何认证信息(credentials)如"cookies"和"HTTP authentication schemes"。除非xhr.withCredentials为true(xhr对象有一个属性叫withCredentials,默认值为false)。
所以根本原因是cookies也是一种认证信息,在跨域请求中,client端必须手动设置xhr.withCredentials=true,且server端也必须允许request能携带认证信息(即response header中包含Access-Control-Allow-Credentials:true),这样浏览器才会自动将cookie加在request header中。
另外,要特别注意一点,一旦跨域request能够携带认证信息,server端一定不能将Access-Control-Allow-Origin设置为*,而必须设置为请求页面的域名。
- expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。这个属性是在http1.0市用来做缓存的,在http1.1基本用max-age替代
- max-age: 与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒),而不是一个固定的时间点。正常情况下,max-age的优先级高于expires。
expires 是 http/1.0协议中的选项,在新的http/1.1协议中expires已经由 max-age 选项代替,两者的作用都是限制cookie 的有效时间。expires的值是一个时间点(cookie失效时刻= expires),而max-age 的值是一个以秒为单位时间段(cookie失效时刻= 创建时刻+ max-age)。
另外,max-age 的默认值是 -1(即有效期为 session );若max-age有三种可能值:负数、0、正数。负数:有效期session;0:删除cookie;正数:有效期为创建时刻+ max-age
- HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。
HttpOnly设置之后浏览器Application/cookies当前域名下的HTTP里面有一个√标识
- secure: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放cookie就对了服务器端设置
secure选项用来设置cookie只在确保安全的请求中才会发送。当请求是HTTPS或者其他安全协议时,包含 secure 选项的 cookie才能被发送至服务器,如果设置了secure属性,在浏览器Application/cookies当前域名下的Secure里面有一个√标识
前端设置cookie
需要每个属性单独设置
document.cookie = "name=zhangsan";
document.cookie = "sex=boy";
document.cookie = "age=20";