写篇文章让自己清楚egg——(4)使用cookie

1,051 阅读4分钟

作为第一次在文章中讲解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界面,查看:

image.png

如果我们不设置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字段自动消失)

image.png

如果没有显示,最好检测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.signedoptions.encrypt,获取传相匹配的值,否则获取不到对应信息

  • 服务器获取请求中的cookie值示例:(自行修改增加逻辑功能)
    console.log(ctx.cookies.get('name', {
      signed: false,
    }));//打印 juejinjin

上面代码中我们创建了name的cookie值,signed和encrypt都是false,所以必须设置signedfalse,才能正确获取信息。encrypt是编码加密方式,而设置时为false,所以获取时可以不写。

补充:浏览器产生cookie

其实cookie一直由浏览器负责创建,只是规范要求服务端发出创建的信息给客户端。

客户端(浏览器)创建cookie:

document.cookie = 'name=juejinjin'
document.cookie = 'pwd=123456'

每次赋值都是创建一个cookie值,当键名相同时cookie进行覆盖。

下一篇我们将动手实现基于egg服务器的含持久化的登录web小项目。