Day23 前端本地存储之cookie

每日一句

You’re never alone when you have books.

释义:有书作陪,永不寂默。

前言

在前端项目实践过程中,如果数据没有存储一旦刷新,网页的数据会丢失。解决这一问题经常用本地存储来实现数据的存储,既方便又快捷!前端实现本地存储的技术主要有cookiesessionStoragelocalStorage

cookie

介绍cookie

image.png

从请求中可以看到携带了cookie。那cookie是啥?

MDN:cookie 是一个请求首部,其中含有先前由服务器通过 Set-Cookie 首部投放并存储到客户端的 HTTP cookies。

document.cookie

只能打印出非httpOnly类型的cookie。

image.png

可以看出是由键值对 key=value构成,键值对之间由一个分号和一个空格隔开。

  • 设置cookie
document.cookie='isLogin=1'
复制代码

这样就给浏览器设置一个简单的cookie,我们可以查看有没有设成功,以chrome为例,打开debug模试:

image.png

从图上可知已设置成功,发现有了name为isLogin, value是1,除了name,value,还有一些可用属性用来控制cookie的作用域,有效期,安全性等。

设置Cookie相关属性

Max-Age

设置cookie的有效期。单位是秒。

  • 为正数:表示可持久化,无论是关闭浏览器或是电脑,只要在该设置的秒值之前,登录该网站都是有效的。

  • 为负数:表示不可持久化,仅在当前窗口或当前窗口打开的子窗口有效,关闭浏览器,登录网站时cookie就会消失,默认是-1。

  • 为0:表示删除该cookie。cookie机制中没有删除cookie的方法,通过设置cookie的有效期为即时失效实现删除该cookie。

expires是旧时的属性,目前正在被Max-Age取代。它的值是为未来过期的毫秒数,默认是当前时间。

Domain

设置cookie的域,这样可以使cookie有条件的共享。默认是当前域,就是当前服务器的主机名。啥叫有条件的共享?比如site.demo.comwww.demo.com,此时这两个子域下的cookie是不共享的,如果我们把这两个子域下设置的cookie都设为demo.com,那么这两个子域下的cookie就可以共享。当然不设置为当前服务器所在之外的域。

特别说明:site.demo.com可以设为site.demo.com(本域)或demo.com(父域),domain不能设为.comcom

path

设置cookie的所在路径,默认是当前网页访问的路径,如:http://site.domeo.com/site,那么path的值就是/site存放在site目录下。如果多目录下设置可能存在访问不到cookie的情况,建议设置到根目下/

httpOnly

增加cookie的安全性,防止网站XSS(Cross SiteScript 跨站脚本)攻击。如果设置了,前端js是获取不到的。

secure

增加cookie的安全性,如果设置Secure=true,只能通过https协议发送给服务器。换句话说就是请求是https下创建的。

cookie是如何工作的

http协议是一种无状态的协议,在web应用程序中,通过http协议进行数据交互,交互完毕后,客户端与服务端的连接就断开。再次交互需要建立新的连接。这种连接无法记录用户的状态,cookie可以弥补HTTP协议无状态的不足。服务器给客户端们颁发一个通行证,无论谁访问都必须携带自己通行证,这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。

clipboard.png

小结

  • 在设置cookie的name,value时,value是不允许有空格,,,;,中文或特殊字符的。如果确实要用得需要编码encodeURIComponent,取值的时候对应转码decodeURIComponent。

  • cookie是以name-value的形式存储本地,每当请求时会带上cookie,如果字符过多就会影响其性能,因此需要尽可能减少cooke,使期传输性能最大化。

  • cookie判别:name,domain,path都相同才是同一个cookie。

  • 更新cookie:只要将key;path;domain一致,则可以通过改变key对应的value来更新cookie的值。

  • 删除cookie:cookie只能更新不能删除,如果想要删除一个cookie,则通过更新设置该cookie的max-age=0即可。

  • cookie的安全性:设置cookie时添加secure。

  • 浏览器在默认情况下是不会发送cookie,需要前端请求时加入配置项。

jq配置:$.ajax({url:'myurl',method:'GET', xhrFields:{withCredentials:true},success:function(){}});

axios配置:axios.defaults.withCredentials = true

后端或中间件如express-cors,koa-cors也需要配置,不然前端报跨域

'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie 
'Access-Control-Allow-Origin': 'http://www.demo.com', // 允许访问的域(协议+域名+端口) /*
'Set-Cookie': 'f=a111;Path=/;Domain=www.demo.com;HttpOnly' // HttpOnly的作用是让js无法读取cookie
复制代码

扩展

  • 实际开发中会借助一些插件js-cookie.或js方法来方便使用cookie.

设置cookie

var username=document.cookie.split(";")[0].split("=")[1];
//JS操作cookies方法!
//写cookies
function setCookie(name,value)
{
var Days = 30;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
复制代码

获取cookie

export function getCookie(...args) {
  let reg, result = [], allCookie = document.cookie, _args = args[0] instanceof Array ? args[0] : args
  _args.forEach(function (val, index) {
    reg = new RegExp("(^| )" + val + "=([^;]*)(;|$)")
    try {
      result.push(unescape(reg.exec(allCookie)[2]))
    } catch (e) {
      if (allCookie.indexOf(val) == -1) {
        result = [""];
      } else {
        console.warn("未知异常")
      }
    }
  })
  return result.length > 1 ? result : result[0]
}
复制代码

(以下为自己封装)

删除Cookie

// 注意:删除cookie时,要看设置cookie是怎么设的,如果设置了domain或path,则在删除时需要传入对的domain或path,没有设置不要传。
// 1.设置的时候没有传domain,默认是当前域,在删除时传了当前域是删不掉的
// 2.设置的时候没有传path,默认是当前的路径,在删除时传了当前路径是可以删除的
export function delCookie(name, options) {
  let exp = new Date(), cval = getCookie(name)
  exp.setTime(exp.getTime() - 1);
  if (cval != null) {
    let delStr= `${name}=${cval};expires=${exp.toGMTString()};`
    if (options && Object.keys(options).length) {
      let { domain = document.domain, path = '/'} = options;
      if (options.path) delStr += `path=${path};`
      if (options.domain) delStr += `domain=${domain};`
    }
    document.cookie = delStr;
  }
}

// 删除多个cookie options 可以是对象(所有都一样参数),可以是数组(对应取小标)
export function delCookies(arr = [], options = {}) {
  if (!arr.length || !Array.isArray(arr)) return;
  arr.forEach((name, index) => {
    if (Array.isArray(options)) {
      delCookie(name, options[index])
    } else {
      delCookie(name, options)
    }
  })
}
复制代码
  • 设置domain中带点与不带点的区别

  • 带点:父域名和任何子域名都可以访问

  • 不带点:只有完全一样的域名才可以访问,IE 除外,仍然支持子域名访问

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享