服务器设置cookie
- 服务设置cookie
``javascript res.header("set-cookie",
token=${resp.id};domain=localhost;path=/;max-age=3600;`);
2. 这种设置的方式有些复杂,可以借助一个`cookie-parser`的中间件
```javascript
const cookieParser = require('cookie-parser')
app.use(cookieParser());
- 设置cookieParser中间件
- 设置以后,会自动在req里面添加cookies属性,用于获取所有带来过来的cookies
- 设置以后,会在res对象中注入cookie方法,用于设置cookie
- app.use(cookieParser(‘1111’)) // 使用111对cookie加密
使用
cookie-parser
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, //此处是毫秒,
// 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
```javascript
app.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)
进行解密,得到加密信息的原始信息