服务器设置cookie
- 服务设置cookie
``javascript res.header("set-cookie",token=${resp.id};domain=localhost;path=/;max-age=3600;`);
2. 这种设置的方式有些复杂,可以借助一个`cookie-parser`的中间件```javascriptconst cookieParser = require('cookie-parser')app.use(cookieParser());
- 设置cookieParser中间件
- 设置以后,会自动在req里面添加cookies属性,用于获取所有带来过来的cookies
- 设置以后,会在res对象中注入cookie方法,用于设置cookie
- app.use(cookieParser(‘1111’)) // 使用111对cookie加密
使用
cookie-parserAdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {// res.header("set-cookie", `token=${resp.id};domain=localhost;path=/;max-age=3600;`);const value = crypter.encrypt(resp.id.toString());res.cookie('token', value, {path: '/',maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,// signed: true 不适用cookie-parser自动加密})res.header('Authorization', value)res.send(getResult(resp))}).catch(err => next(err))
服务器检验cookie中的信息
用一个中间件,来验证客户端的需要验证的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. needTokenApi: 需要验证cookie信息的的请求1. pathToRegexp: 是一个把动态路径规则`/api/student/:id`转换为正则表达式,用来匹配是否满足动态路径规则的的请求1. 此中间件中的`throw Error('you have not access the api');`会触发错误,会被处理错误的中间件捕捉到,进行处理<a name="VwXki"></a>## cookie中信息加密1. express开启加密,非对撑加密,秘钥是111```javascriptapp.use(cookieParser('1111')) // 使用111对cookie加密
- 使用加密
AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {const value = crypter.encrypt(resp.id.toString());res.cookie('token', value, {path: '/',maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,signed: true})res.header('Authorization', value)res.send(getResult(resp))}).catch(err => next(err))
- signed:true, 加密传输cookie信息,
- cookie的秘钥在服务器,很难获取到,比较安全
- 自动加密,因为无法知道加密方法,就会导致我们需要加密其他内容的时候,无法采用同样的加密方法,例如:
- 在没有浏览器的设备上,我们一般使用在header里面的添加属性来兼容不能使用cookie的设备商
- 这样的话,就无法和具有浏览器设备上的加密方法保持一致
自定义加密
// 使用对称加密算法:aes 128// 128位的秘钥const secret = Buffer.from("mm7h3ck87ugk9l4a");const crypto = require("crypto"); // 内置加密库// 准备一个iv,随机向量const iv = Buffer.from("jxkvxz97409u3m8c");exports.encrypt = function (str) {const cry = crypto.createCipheriv("aes-128-cbc", secret, iv);let result = cry.update(str, "utf-8", "hex");result += cry.final("hex");return result;};exports.decrypt = function (str) {const decry = crypto.createDecipheriv("aes-128-cbc", secret, iv);let result = decry.update(str, "hex", "utf-8");result += decry.final("utf-8");return result;};
- 使用encrypt来进行解密
- 使用decrypt来进行解密
const express = require('express');const router = express.Router();const { getResult } = require('./sendHelper');const AdminService = require('../../services/adminService');const crypter = require('../../util/crypt')router.get('/', (req, res, next) => {const { loginName, loginPwd } = req.query;AdminService.getAdminByLoginPwdAndLoginName(loginName, loginPwd).then(resp => {// res.header("set-cookie", `token=${resp.id};domain=localhost;path=/;max-age=3600;`);const value = crypter.encrypt(resp.id.toString());res.cookie('token', value, {path: '/',maxAge: 7 * 24 * 3600 * 1000, //此处是毫秒,})res.header('Authorization', value)res.send(getResult(resp))}).catch(err => next(err))})router.post('/', (req, res, next) => {AdminService.addAdmin(req.body).then(resp => {res.send(getResult(resp))}).catch(err => next(err))})module.exports = router;
以上value被自定义的value = crypter.encrypt(resp.id.toString());加密方法加密过,分别给了cookie和header,保持加密方法一致性
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();}
使用ceyptor.decrypt(req.cookies.token)进行解密,得到加密信息的原始信息
