cookie 介绍
- cookie是存储在浏览器的一段字符串(最大5kb)
- 跨域不共享
- 比如:你同时打开了淘宝和百度,那么淘宝和百度对应的是2个cookie,他们是不共享的。
- 格式如
k1=v1;k2=v2;k3=v3;
因此可以存储结构化数据 - 每次发送http请求,会将请求域的cookie一起发送给server端
- 比如:你在淘宝中请求访问百度,那么就会将百度的cookie发送给server端。
- server端可以修改cookie并返回给浏览器
- 浏览器中也可以通过javascript修改cookie(有限制)
客户端JS操作cookie
客户端(浏览器)查看cookie的三种方式
- 方式1 f12-Network:
- 客户端通过请求头将cookie传给服务端:
- 服务端将处理好的cookie通过响应头返回给客户端:
- 接下来客户端就可以使用服务端返回的cookie。
- 方式2 f12-Application-Cookies-找到对应域名:
- 这里面是解析过的cookie值:
- path为
/
即该网页下cookie都生效,不管是https://www.baidu.com/
还是https://www.baidu.com/???xxx/yyy
- 可手动删除cookie:
- 方式3 通过JS查看(有限制):
JS查看、累加cookie(有限制)
- 可以通过JS查看cookie(上面的方式3),也可以累加cookie(有限制),但不能删除cookie。
- 累加cookie和查看cookie的方法一样:
- 但其实有了本地存储Local Storage后,js修改cookie变得很少:
server端nodejs操作cookie
获取cookie
在server端可通过req.headers.cookie
获取到cookie(req是http请求),因为cookie是保存在请求头部的。
操作cookie
server端可以将cookie通过res的setHeader方法设置到响应报文头部的Set-Cookie中,比如(res是http响应报文):
1 | res.setHeader(`Set-Cookie`, `username=${data.username}; path=/`); |
cookie用于登录验证
app.js获取cookie转为对象
blog-1中app.js,解析cookie,cookie为字符串,不好操作,所以将其转换为对象后放到req身上方便调用:
- 使用字符串的split方法将字符串分隔为数组。
- 使用数组的forEach方法将每个数组元素都分隔后放入对象中作为属性和属性值。
测试:刷新页面,获取到请求中的cookie并打印出来:
router-user.js创建测试登录验证的路由
- ctrl+shift+a+f将所有logincheck改为login:
- 创建一个路由用于测试登录验证:
- app.js需要路由返回一个Promise对象,所以使用Promise.resolve()来快速创建一个Promise对象。
- 测试:
router-user.js测试登录
- 暂时将登录改为get,方便测试:
- 操作cookie
- 测试:
解决cookie的属性前有空格的问题
注意:如果原本就有cookie则无法登录成功,因为后面加入的username字符串前出现空格,导致无法获取username:
解决方法:在app.js中,解析cookie时,使用字符串的trim()删除字符串的头尾空格,这样就能获取到username:
字符串的trim()
- 字符串的trim()删除字符串的头尾空格。
- 不会改变原始字符串。
server端给JS操作cookie做限制
- 要给JS操作cookie做限制,cookie中某些数据是不能修改的。
- 后端设置cookie时加上
httpOnly
即可,表示只允许后端修改。
为什么要做限制
因为此时前端可修改cookie中的username,不安全:
给cookie做限制
router-user.js中,设置cookie时加上httpOnly
即可,表示只允许后端修改:
测试:
- 先传入username和password:
- 通过测试路由可看到httpOnly设置成功:
- 此时前端无法获取username,修改不会报错也不会成功:
- 修改username增添的只是假数据:
设置cookie过期时间(expires)
可以看到此时cookie是不会过期的:
- router-user.js中,给cookie加属性expires,设置24小时后过期:
- toGMTString() 方法可根据格林威治时间 (GMT) 把 Date 对象转换为字符串,并返回结果。
- 不赞成使用此toGMTString方法。请使用 toUTCString() 取而代之!!得到的结果是一样的:
- 测试:
- toGMTString打印结果: