博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cookie
阅读量:6070 次
发布时间:2019-06-20

本文共 3293 字,大约阅读时间需要 10 分钟。

cookie的原理

何为 cookie 呢?我们在上面了解到 HTTP 是无状态的,但随着 Web 的不断发展,这种 无状态 的特性出现了弊端。当你登录到一家购物网站,在跳转到该站的其他页面时也应该继续保持登录状态。但是因为 HTTP 是无状态的,所以必须得在浏览器端存储一些信息来标识当前用户,因此 cookie 应运而生,它一种浏览器管理状态的文件。

浏览器第一次发出请求,服务器会将 cookie 放入到响应请求中,在浏览器第二次发请求的时候,会把 cookie 带过去,于是服务端就会辨别用户身份。注意:单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。

cookie 在请求头中有一个 cookie 字段,在响应头里有一个 set-cookie 字段。

cookie 是不可跨域的

cookie 本身就是用来保存一些隐私性的字段,基于安全性的考量,必须要保证它是 不可跨域的。我们可以做个实验:先打开 ,然后在开发者工具中输入以下代码:

document.cookie = 'hello=world;path=/;domain=.baidu.com';document.cookie = 'world=hello;path=/;domain=.google.com';复制代码

打开 Application 选项卡,在侧边栏找到 Cookies,可以发现只有 domain 为 .google.com 的被成功添加。

cookie 的属性

我们通过一个登录的小例子来了解服务端设置 cookie。首先通过 express application generator 生成一个 Express 工程。

接着在 index.html 文件中输入以下代码,我们创建一个输入用户名和密码的界面,在点击按钮的时候,通过 fetch 将输入的值发送给后端。

Login

登录状态:

复制代码

当用户名和密码匹配时 (假设用户名和密码都是 yancey),返回给客户端一个 cookie 以及登录成功的 json;否则返回登录失败的 json。下面是模拟服务端登录的接口。

router.post('/login', (req, res, next) => {  const body = req.body;  if (body.userName === 'yancey' && body.userPwd === 'yancey') {    // 设置 cookie    res.cookie('yancey', 'success');    res.json({      success: true,      msg: '登录成功'    });  } else {    res.status(401).json({      success: false,      msg: '用户名或密码错误'    });  }});复制代码

通过这个例子可以看到,在 express 中,setCookie 的方式为:第一个参数传递 name,第二个参数传递 value,注意浏览器会将元字符和语义字符之外的字符进行转义。打开 Chrome 的开发者工具,就可以看到该 cookie 被添加到浏览器上了。或者你在控制台输入 document.cookie,同样可以看到 cookie 字符串。

这只是一个设置 cookie 的简单例子,cookie 有 7 种属性可供使用,我们一一来了解。

domain

该属性给 cookie 设置 域名,默认为当前网站的域名,下面的例子将 domain 设为 yanceyleo.com,由于前端页面是 127.0.0.1,根据同源策略,该条 cookie 不会生效。

res.cookie('domain', 'domian', { domain: 'yanceyleo.com' });复制代码

expires / maxAge

httpOnly

当该属性设为 true 时,document.cookie 将无法获取该条 cookie,但服务端可以照常获得。该属性可以有效的避免跨站脚本攻击 (XSS)。 `

res.cookie('httpOnly', 'httpOnly', {  // 只能被 web server 访问到,也就是说在浏览器输入 document.cookie 无法取到该条 cookie,目的是防止 xss  httpOnly: true});复制代码

path

该属性给 指定的路径 添加此 cookie,默认为 /。如下代码就是给 users 这个路由设置 cookie (即便在服务端该路径不存在也会被添加上)。

res.cookie('path', 'path', {  path: '/users'});复制代码

secure

只有当连接是 HTTPS 协议,该 cookie 才会被添加。该属性默认为 fasle。因为我本地的 express 是 HTTP 协议,因此该条 cookie 不会生效。

res.cookie('secure', 'secure', {  secure: true});复制代码

signed (防篡改签名)

该属性是给浏览器发送一个加密的 cookie,该属性默认为 false。在 express 中,我们可以使用 cookie-parser 插件来创建一个加密后的 cookie。服务端通过该 cookie 的内容和签名来检验它是否 被篡改

首先给 cookieParser 传入一个 secret。

app.use(cookieParser('forcabarca'));然后返回一个 sign 后的 cookie。res.cookie('signed', 'signed', {  signed: true});复制代码

在 express 中,我们可以使用 req.cookies 来获得 未加密 的 cookie 对象,可以通过 req.signedCookies 来获得 已加密 的 cookie 对象。

console.log(req.cookies); // { httpOnly: 'httpOnly' }console.log(req.signedCookies); // { signed: 'signed' }复制代码

session

ession 是服务端使用的一种记录客户端状态的机制,与 cookie 不同的是,session 保存在 服务端。当客户端初次发送请求时 (比如登录成功),服务端会将用户信息以某种形式保存在服务端,当再次访问时只需从该 session 中找到该客户的状态即可。

因此,cookie 机制就是通过检查客户身上的 “通行证” 来确定客户身份,而 session 则是通过检查服务器上的 “客户明细表” 来确认客户身份。session 相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

因为 HTTP 是无状态的,所以单纯的 session 仍不能判断是否为到底是哪个用户。因此服务端仍要向客户端发送一个 maxAge 为 -1 的 cookie 来作为不同用户的唯一标识。

当然你也可以不使用 cookie,你可以通过重写 URL 地址的方式来实现。它的原理是将用户的 seesion id 写入到 URL 中,当浏览器解析新的 URL 时就可以定位到是哪位用户。

万变不离其宗,两种方式都是要保证用户信息以某种形式保存到客户端。更先进的 localStorage,sessionStorage,IndexedDB 也是同样的道理,这里不去细说。

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

你可能感兴趣的文章
枸杞子也能控制脂肪肝
查看>>
Excuse me?这个前端面试在搞事!
查看>>
C#数据采集类
查看>>
quicksort
查看>>
检验函数运行时间
查看>>
【BZOJ2019】nim
查看>>
Oracle临时表空间满了的解决办法
查看>>
四部曲
查看>>
LINUX内核调试过程
查看>>
【HDOJ】3553 Just a String
查看>>
Java 集合深入理解(7):ArrayList
查看>>
2019年春季学期第四周作业
查看>>
linux环境配置
查看>>
ASP.NET MVC中从前台页面视图(View)传递数据到后台控制器(Controller)方式
查看>>
lintcode:next permutation下一个排列
查看>>
python 递归
查看>>
一个想法(续二):换个角度思考如何解决IT企业招聘难的问题!
查看>>
tomcat指定配置文件路径方法
查看>>
linux下查看各硬件型号
查看>>
对象合成复用之策略模式
查看>>