Cookie

HTTP 请求都是无状态的,但是我们的 Web 应用通常都需要知道发起请求的人是谁。为了解决这个问题,HTTP 协议设计了一个特殊的请求头:Cookie。服务端可以通过响应头(set-cookie)将少量数据响应给客户端,浏览器会遵循协议将数据保存,并在下次请求同一个服务的时候带上(浏览器也会遵循协议,只在访问符合 Cookie 指定规则的网站时带上对应的 Cookie 来保证安全性)。

全局配置

public/user.js

  1. const login = () => {
  2. fetch('/login', {
  3. method: 'post',
  4. headers: {
  5. 'Content-type': 'application/json',
  6. },
  7. body: JSON.stringify({
  8. name: 'admin',
  9. pwd: 'admin',
  10. }),
  11. });
  12. };

controller/user.js

  1. async login() {
  2. const { ctx } = this;
  3. const body = ctx.request.body;
  4. ctx.cookies.set('user', JSON.stringify(body));
  5. //这里就是响应
  6. ctx.body = {
  7. status: 200,
  8. data: body,
  9. };
  10. }

egg 集成了 操作 cookie 的方法在ctx 中。

还要记得配置路由

  1. router.post('/login', controller.user.login);

开发者工具显示

响应
image.png
Cookie
image.png


想在视图中展示——即在 html 中拿到 cookies 中的数据:

  1. <% if(user){ %>
  2. 已经登录:<%= user.name %>
  3. <% }else{ %>
  4. 未登录
  5. <% } %>

controller/user

  1. async index() {
  2. const { ctx } = this;
  3. // ctx.body = 'hi, user index';
  4. const user = ctx.cookies.get('user'); //**
  5. await ctx.render(
  6. 'user.html',
  7. {
  8. id: 100,
  9. name: 'admin',
  10. lists: ['java', 'php'],
  11. user: user ? JSON.parse(user) : null, //**
  12. },
  13. {
  14. delimiter: '%',
  15. }
  16. );
  17. }

注销

  1. async logout() {
  2. const { ctx } = this;
  3. ctx.cookies.set('user', null);
  4. ctx.body = {
  5. status: 200,
  6. };
  7. }

但此时从开发者工具中查看 cookies是实时更新了,页面却没有实时更新
再到前面 login、logout 里面的 fetch 连接then—— fetch 返回 Promise

  1. const logout = () => {
  2. fetch('/logout', {
  3. method: 'post',
  4. headers: {
  5. 'Content-type': 'application/json',
  6. },
  7. body: JSON.stringify({}),
  8. }).then(() => {
  9. location.reload();
  10. });
  11. };

ctx.cookies.set 配置项

配置时间

  1. ctx.cookies.set('user', JSON.stringify(body), {
  2. maxAge: 1000 * 60, //cookie 保留一分钟
  3. httpOnly: true
  4. });

cookies 属性 httpOnly: √ 表示只能从服务端操作该 cookies ,而不能在前端js 操作 cookies


设置中文 Cookies

如果你直接这样

  1. ctx.cookies.set('ch', '中文');

那么浏览器就会直接报错

方法一 加密

你可以选择进行加密:

  1. ctx.cookies.set('zh', '中文', {
  2. encrypt: true,
  3. });

加密后就不是中文了,自然就可行了
此时如果直接访问

  1. const zh = ctx.cookies.get('zh');
  2. console.log(zh);

结果是 undefined
解密

  1. ctx.cookies.set('zh', '中文', {
  2. encrypt: true,
  3. });
  4. const zh = ctx.cookies.get('zh', {
  5. encrypt: true,
  6. });
  7. console.log(zh);

方法二 base64 编码

  1. class UserController extends Controller {
  2. encode(str) {
  3. return new Buffer(str).toString('base64');
  4. }
  5. decode(str) {
  6. return new Buffer(str, 'base64').toString;
  7. }
  8. //...
  9. async index(){
  10. //...
  11. ctx.cookies.set('base64', this.encode('中文base64'));
  12. const base64 = this.decode(ctx.cookies.get('base64'));
  13. console.log(base64);
  14. }