服务器设置cookie

  1. 服务设置cookie ``javascript res.header("set-cookie",token=${resp.id};domain=localhost;path=/;max-age=3600;`);
  1. 2. 这种设置的方式有些复杂,可以借助一个`cookie-parser`的中间件
  2. ```javascript
  3. const cookieParser = require('cookie-parser')
  4. app.use(cookieParser());
  • 设置cookieParser中间件
  • 设置以后,会自动在req里面添加cookies属性,用于获取所有带来过来的cookies
  • 设置以后,会在res对象中注入cookie方法,用于设置cookie
  • app.use(cookieParser(‘1111’)) // 使用111对cookie加密
  1. 使用cookie-parser

    1. AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {
    2. // res.header("set-cookie", `token=${resp.id};domain=localhost;path=/;max-age=3600;`);
    3. const value = crypter.encrypt(resp.id.toString());
    4. res.cookie('token', value, {
    5. path: '/',
    6. maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,
    7. // signed: true 不适用cookie-parser自动加密
    8. })
    9. res.header('Authorization', value)
    10. res.send(getResult(resp))
    11. }).catch(err => next(err))

    服务器检验cookie中的信息

  2. 用一个中间件,来验证客户端的需要验证的cookie信息的 ```javascript

const { pathToRegexp } = require(‘path-to-regexp’); const ceyptor = require(‘../../util/crypt’) const needTokenApi = [ { method: ‘POST’, path: ‘/api/student’ }, { method: ‘PUT’, path: ‘/api/student/:id’ } ] module.exports = function (req, res, next) { const apis = needTokenApi.filter(api => { return api.method === req.method && pathToRegexp(api.path).test(req.path); }) if (apis.length === 0) { next(); return; } let token = req.cookies.token || req.headers.Authorization; //未加密 console.log(‘req.cookies.token’, ceyptor.decrypt(req.cookies.token)) // 解密token // let token = req.signedCookies.token || req.headers.Authorization; 不使用,因为自动加密,header无法加密 if (!token) { throw Error(‘you have not access the api’); } next(); }

  1. 1. needTokenApi: 需要验证cookie信息的的请求
  2. 1. pathToRegexp: 是一个把动态路径规则`/api/student/:id`转换为正则表达式,用来匹配是否满足动态路径规则的的请求
  3. 1. 此中间件中的`throw Error('you have not access the api');`会触发错误,会被处理错误的中间件捕捉到,进行处理
  4. <a name="VwXki"></a>
  5. ## cookie中信息加密
  6. 1. express开启加密,非对撑加密,秘钥是111
  7. ```javascript
  8. app.use(cookieParser('1111')) // 使用111对cookie加密
  1. 使用加密
    1. AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {
    2. const value = crypter.encrypt(resp.id.toString());
    3. res.cookie('token', value, {
    4. path: '/',
    5. maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,
    6. signed: true
    7. })
    8. res.header('Authorization', value)
    9. res.send(getResult(resp))
    10. }).catch(err => next(err))
  • signed:true, 加密传输cookie信息,
  • cookie的秘钥在服务器,很难获取到,比较安全
  • 自动加密,因为无法知道加密方法,就会导致我们需要加密其他内容的时候,无法采用同样的加密方法,例如:
    • 在没有浏览器的设备上,我们一般使用在header里面的添加属性来兼容不能使用cookie的设备商
    • 这样的话,就无法和具有浏览器设备上的加密方法保持一致

自定义加密

  1. // 使用对称加密算法:aes 128
  2. // 128位的秘钥
  3. const secret = Buffer.from("mm7h3ck87ugk9l4a");
  4. const crypto = require("crypto"); // 内置加密库
  5. // 准备一个iv,随机向量
  6. const iv = Buffer.from("jxkvxz97409u3m8c");
  7. exports.encrypt = function (str) {
  8. const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);
  9. let result = cry.update(str, "utf-8", "hex");
  10. result += cry.final("hex");
  11. return result;
  12. };
  13. exports.decrypt = function (str) {
  14. const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);
  15. let result = decry.update(str, "hex", "utf-8");
  16. result += decry.final("utf-8");
  17. return result;
  18. };
  • 使用encrypt来进行解密
  • 使用decrypt来进行解密
  1. const express = require('express');
  2. const router = express.Router();
  3. const { getResult } = require('./sendHelper');
  4. const AdminService = require('../../services/adminService');
  5. const crypter = require('../../util/crypt')
  6. router.get('/', (req, res, next) => {
  7. const { loginName, loginPwd } = req.query;
  8. AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {
  9. // res.header("set-cookie", `token=${resp.id};domain=localhost;path=/;max-age=3600;`);
  10. const value = crypter.encrypt(resp.id.toString());
  11. res.cookie('token', value, {
  12. path: '/',
  13. maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,
  14. })
  15. res.header('Authorization', value)
  16. res.send(getResult(resp))
  17. }).catch(err => next(err))
  18. })
  19. router.post('/', (req, res, next) => {
  20. AdminService.addAdmin(req.body).then(resp => {
  21. res.send(getResult(resp))
  22. }).catch(err => next(err))
  23. })
  24. module.exports = router;

以上value被自定义的value = crypter.encrypt(resp.id.toString());加密方法加密过,分别给了cookie和header,保持加密方法一致性

  1. const { pathToRegexp } = require('path-to-regexp');
  2. const ceyptor = require('../../util/crypt')
  3. const needTokenApi = [
  4. { method: 'POST', path: '/api/student' },
  5. { method: 'PUT', path: '/api/student/:id' }
  6. ]
  7. module.exports = function (req, res, next) {
  8. const apis = needTokenApi.filter(api => {
  9. return api.method === req.method && pathToRegexp(api.path).test(req.path);
  10. })
  11. if (apis.length === 0) {
  12. next();
  13. return;
  14. }
  15. let token = req.cookies.token || req.headers.Authorization; //未加密
  16. console.log('req.cookies.token', ceyptor.decrypt(req.cookies.token)) // 解密token
  17. // let token = req.signedCookies.token || req.headers.Authorization; 不使用,因为自动加密,header无法加密
  18. if (!token) {
  19. throw Error('you have not access the api');
  20. }
  21. next();
  22. }

使用ceyptor.decrypt(req.cookies.token)进行解密,得到加密信息的原始信息