作为第一次在文章中讲解cookie,我觉得应该详细一些,为日后其他部分讲解cookie做基础和参考。
egg
中使用cookie
不需要插件,而是内置在ctx对象原型上,使用方法进行配置生成。因为http
请求中cookie
是从header
中传输过来的。
cookie
,曲奇小饼干。是一种web缓存机制,先于WebStorage
应用于网站开发,目前主要用于用户登录状态持久化
等功能。
cookie
名字来源假说: 通俗来说,服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,于是就诞生了Cookie;我们可以把Cookie 理解为一个存储在浏览器里的一个小小的文本文件,它附着在 HTTP 请求上,在浏览器和服务器之间“飞来飞去”。
产生cookie
通过 ctx.cookies
,我们可以在 controller
中便捷、安全的设置和读取 Cookie
。
这里我们在controller
文件夹下创建cookie.js文件:
cookie.js 完整代码
'use strict';
const Controller = require('egg').Controller;
class CookieController extends Controller {
async index() {
const { ctx } = this;
ctx.cookies.set('name', ctx.request.body.name, {
maxAge: 50000,//cookie从最后一次更新在客户端后保持的时间(ms),timeout就会去除在本地的这部分cookie信息。
path: '/',
domain: 'juejinjin.com',//该属性决定了当前网页能不能显示和使用cookie。
httpOnly: false,//该属性告诉浏览器cookie能不能被修改,true就是只能被传输不能修改。
signed: false,
encrypt: false,
});
ctx.body = ctx.request.body;
}
}
module.exports = CookieController;
router.js也需要配置一下路由,参考之前文章。
客户端网页js代码
setTimeout(() => {
let xhr = new XMLHttpRequest();
xhr.open('post','http://juejinjin.com/cookie',true);//新路由
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload=function(){
console.log('响应')
console.log(JSON.parse(xhr.responseText))
}
xhr.send("name=juejinjin&age=12");
xhr.onerror=function(){
console.log('err')
}
}, 200);
我们先打开控制台的NetWork
界面,查看:
如果我们不设置ctx.cookies.set方法的第三个options参数对象信息,最坏也能在NetWork界面的具体响应报文里查看到cookie信息。
展示cookie
我们设置了ctx.cookies.set
方法的第三个参数options:(所以我们通过开发者工具查看服务器响应给网页的具体cookie
信息)
{
maxAge: 50000,//cookie从最后一次更新在客户端后保持的时间(ms),timeout就会去除在本地的这部分cookie信息。
path: '/',
domain: 'juejinjin.com',//该属性决定了当前网页能不能显示和使用cookie(Application界面)。⭐
httpOnly: false,//该属性告诉浏览器cookie能不能被修改,true就是只能被传输不能修改。
signed: false,
encrypt: false,//是否加密编码,true的话我们看到的cookie是加密过后的。
}
因为配置好的cookie
的信息,当网页发送完请求后,可以打开控制台进入Application
界面。我们会看到:(我们设置的50000ms过期时间,等待后即可看到name字段自动消失)
如果没有显示,最好检测domain
属性(cookie
产生作用的关键配置)。
携带cookie
说完产生cookie
和查看cookie
,我们还需要每次携带cookie
进行状态的保持,实现登录持久化
等效果。
- 客户端获取
cookie
(部分js代码)
...//load事件中,我们可以向文档获取cookie信息,因为响应而来的cookie会持久化在本地。
xhr.onload=function(){
console.log('响应')
console.log(JSON.parse(xhr.responseText))
console.log(document.cookie)//获取到在本地的cookie。
}
...
- 请求时携带
cookie
(部分js代码)
xhr.withCredentials = true; //放在send方法之前,让cookie跟随请求发送给服务器。
有些浏览器会默认为携带cookie,不过建议始终书写该代码。
查询cookie
登录状态持久化
的功能实现,除了由服务器在第一次登录时产生登录的状态信息(cookie
)发送给客户端,客户端再次打卡网站内网页时携带登录信息(cookie
),此时我们还剩下一步——服务器对请求中的登录信息(cookie
)进行验证。
因为cookie通常是从请求header
中传输过来的,通过ctx.cookies.get
快速获取值,在获取时注意options.signed
和 options.encrypt
,获取传相匹配的值,否则获取不到对应信息。
- 服务器获取请求中的
cookie
值示例:(自行修改增加逻辑功能)
console.log(ctx.cookies.get('name', {
signed: false,
}));//打印 juejinjin
上面代码中我们创建了name的
cookie
值,signed和encrypt都是false
,所以必须设置signed
为false
,才能正确获取信息。encrypt
是编码加密方式,而设置时为false
,所以获取时可以不写。
补充:浏览器产生cookie
其实cookie一直由浏览器负责创建,只是规范要求服务端发出创建的信息给客户端。
客户端(浏览器)创建cookie:
document.cookie = 'name=juejinjin'
document.cookie = 'pwd=123456'
每次赋值都是创建一个cookie值,当键名相同时cookie进行覆盖。
下一篇我们将动手实现基于egg服务器的含持久化的登录web小项目。