Cookie小记


> 需求描述:理解cookie



维持登录态的几种方式:

传统身份验证的方法

HTTP 是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。

解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的 ID 号发送给客户端,客户端收到以后把这个 ID 号存储在 Cookie 里,下次这个用户再向服务端发送请求的时候,可以带着这个 Cookie ,这样服务端会验证一个这个 Cookie 里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。

上面说的就是 Session,我们需要在服务端存储为登录的用户生成的 Session ,这些 Session 可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的 Session 。

基于 Token 的身份验证方法

使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

1、客户端使用用户名跟密码请求登录
2、服务端收到请求,去验证用户名与密码
3、验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

Cookie


Cookie种类


1、临时Cookie(会话Cookie)
2、永久Cookie

cookie分为两种,一种是硬盘上的,另一种是内存上的,一个网站通常有一个.txt文件来存Cookies,一个Cookie对象最终转换为txt文件中的一条记录。保存在浏览器线程分配的内存中的Cookie对象,在关闭这个浏览器窗口后,就销毁了。导致种类不同是过期时间的设置与否决定的,如果设置了过期时间,那么就会在过期时间未到前一直生效,请求会被携带,除非服务端设置了max-age强制使其失效;而没有设置过期时间,cookie的生命周期只存在于浏览器会话期间,关闭窗口,cookie即消失。

Cookie被携带的条件

同一域名下,存在cookie,浏览器会默认自动发送Cookie给对应的服务器。
普通的ajax(json)请求和jsop跨域请求是默认携带cookie的,而cors跨域请求和fetch请求默认是不携带cookie的。因此,当我们的请求需要携带cookie时,我们就要对cors跨域请求和fetch请求这两中请求方式进行特殊配置处理。
通常我们使用的axios库,也是对XMLHttpRequest这个对象的封装,和ajax请求无异,因为加入了promise,解决了回调的问题。
而fetch请求如果想携带cookie,需要设置header里面的参数,加上credientials: ‘include’;
CORS的方式想要携带cookie,需要设置如下设置

// aixos为例const service = axios.create({baseURL: process.env.BASE_API, // node环境的不同,对应不同的baseURLtimeout: 30000, // 请求的超时时间withCredentials: true // 允许携带cookie})复制代码


设置Cookie的方式

1、后端设置set-cookie,这种情况下,前端什么也不需要做。相当于服务器端给浏览器发送指令,浏览器自动注入cookie;,每次请求都携带cookie信息;
2、前端收到后端返回的信息,设置cookie;

function setDomainCookie(name, value, expiresDays = 60, host) {let date = new Date();date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);const expires = `expires=${date.toGMTString()};`;host? '': (host = window.location.hostname.split('.').slice(-2).join('.'));const domain = `domain=${host};`;window.document.cookie = `${name}=${value};${expires}${domain}path=/`;}复制代码


分析 && 总结
1、cookie信息自动被请求携带,不限于请求后端数据的请求,即使是刷新页面,图片,css,js,也都会携带本地的cookie信息,这无疑相当于浪费了请求头的资源;
2、cookie是不允许跨域传输的,所以在本地localhost发送的请求是不会被携带到请求头里的,这样就会有问题,如果很多请求都需要验证权限,而开发环境又无法携带cookie信息,就会带来联调上的困难;
3、cookie中能够存储的数据有限,不同的浏览器限制大小不一样。

综上,在实现自动登录时,前端收到服务端返回的token,可以存到localstorage里,然后塞入请求头中,所有对于数据的请求都会携带此头部字段,虽然localstorage没有过期这一概念,我们可以自己手动设置,每次发送请求前都判断一遍是否过期,如下:

// 存入if (cacheParams.cacheTime < 0) cacheParams.cacheTime = 3600000;var result = { data: response.data, expiration: new Date().getTime() + cacheParams.cacheTime };localStorage.setItem(cacheParams.cacheName, JSON.stringify(result));// 取出判断const data = JSON.parse(data);if (parseInt(data.expiration) - new Date().getTime() <= 3000) {// 说明已过期,做相应处理}复制代码

设置请求头:

// 以axios实例为例netApi.interceptors.request.use((request) => {removePending(request); // 在一个ajax发送前执行一下取消操作config.cancelToken = new APICancelToken((c) => {// 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式pending.push({ u: `${request.url}&${request.method}`, f: c });});if (readLocalStorage('X-Token')) {request.headers.token = readLocalStorage('X-Token'); // 携带token}return request;}, error => Promise.reject(error));复制代码

题外记,如果存有登录信息的cookie文件,被复制到另一台设备的指定目录下,去访问这个cookie对应的网站,是不是也能正常访问呢?
我的理解是可以的,或者换一种方式,我的设备上的cookie信息被劫持了,然后被用来登录我使用的网站了,是不是意味着这个人在行驶着我的权力,理论上是,可是现在的安全防范策略那么多,能够存到cookie里的信息未必是最重要的明文信息,所以即使被劫持了也影响不大。


欢迎指正!


参考文章:
1、[React16新的生命周期函数getDerivedStateFromProps的使用,你也许并不需要派生状态【译】](https://blog.csdn.net/nnxxyy1111/article/details/80832525)
2、[HTTP--Request Headers及Cookies](https://www.cnblogs.com/wxinyu/p/8005621.html)
3、[状态保持中的Cookie与Session](https://blog.csdn.net/sundacheng1989/article/details/8194466)
4、[CORS简介](https://www.cnblogs.com/loveis715/p/4592246.html)
5、[axios的cookie跨域以及相关配置
](https://segmentfault.com/a/1190000011811117?utm_source=tag-newest)


转载于:https://juejin.im/post/5be977216fb9a049ad769360

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值