一、关于cookie加密
cookie加密是让客户端无法获取cookie明文信息,是数据安全的重要部分;一般的我们可以在保存cookie前,先前cookie信息进行加密,或者在res.cookie设置cookie时对option配置对象的signed属性设置成true也可以实现。
二、配置 signed 属性加密
在设置中间件时传入参数‘secret’字符串
//不使用加密时
//app.use(cookieParser())
//使用加密时,传入加密字符串
app.use(cookieParser('ByCXyqxH'))
设置cookie时在配置参数对象中添加signed属性
let option = {
maxAge:30*60*1000,
signed:true
}
res.cookie('token',token,option)
获取加密的token
//未使用signed时
//req.cookies.token
//使用signed后
req.signedCookies.token;
完整案例:
对token 字符串 318514ae-83b9-47ab-947a-86f828b391e9 加密
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser')
//添加自定义的加密字符串 ‘ByCXyqxH’,
app.use(cookieParser('ByCXyqxH'))
app.get('/set',(req,res,next)=>{
let token = '318514ae-83b9-47ab-947a-86f828b391e9';
//添加signed属性
let option = {
maxAge:30*60*1000,
signed:true
}
res.cookie('token',token,option)
res.send('success')
})
app.get('/get',(req,res,next)=>{
//获取加密的cookie
let token = req.signedCookies.token;
console.log(token)
res.send("token:" + (token || 'null'))
})
module.exports = app;
签名原理
Express用于对cookie签名,而cookie-parser则是实现对签名的解析。实质是把cookie设置的值和cookieParser(‘ByCXyqxH’)中的ByCXyqxH进行hmac加密之后和cookie值加“.”的方式拼接起来(注意观察加密后的字符串中间有个“.”)。
当option中signed设置为true后,底层会将cookie的值与“secret”进行hmac加密;
如何解析
cookie-parser中间件在解析签名cookie时做了两件事:
- 将签名cookie对应的原始值提取出来
- 验证签名cookie是否合法
三、直接对cookie值加密
node为我们提供了一个核心安全模块“crypto”,它提供了很多安全相关的功能,如摘要运算、加密、电子签名等。
我们可以使用crypto模块轻易的封装一个加密函数或加密模块:
封闭加密函数
//引入crypto模块
var crypto = require('crypto');
//加密盐值
const md5_salt = "ByCXyqxH";
//MD5加密
function md5(str){
let obj = crypto.createHash('md5');
obj.update(str + md5_salt);
return obj.digest('hex');
}
或者封闭为一个模块md5.js,在使用的地方进行引入
//引入crypto模块
var crypto = require('crypto');
//加密盐值
const md5_salt = "ByCXyqxH";
//MD5加密
function md5(str){
let obj = crypto.createHash('md5');
obj.update(str + md5_salt);
return obj.digest('hex');
}
module.exports = {md5:md5};
引入封装的md5模块
var md5 = require('./md5');
完整案例:
var express = require('express');
var crypto = require('crypto');
var app = express();
var cookieParser = require('cookie-parser')
app.use(cookieParser())
//加密盐值
const md5_salt = "ByCXyqxH";
//封装加密函数
function md5(str){
let obj = crypto.createHash('md5');
obj.update(str + md5_salt);
return obj.digest('hex');
}
var token = '318514ae-83b9-47ab-947a-86f828b391e9';
app.get('/set',(req,res,next)=>{
//对token进行加密
let signedToken = md5(token);
//将加密的token设置到cookie中
res.cookie('token',signedToken,{maxAge:30*60*1000})
res.send('success:' + token)
})
//验证token
app.get('/verify',(req,res,next)=>{
//将服务端保存的token进行加密 再与 获取的cookie中加密后的token进行比较
let cookieToken = req.cookies.token;
console.log("cookieToken:" + cookieToken)
let signedToken = md5(token);
console.log("signedToken:" + signedToken)
if(cookieToken === signedToken){
res.send("eq:" + true)
}else{
res.send("eq:" + false)
}
})
module.exports = app;
如果是在校验登录密码时,只需将用户输入的密码进行同样加密操作再进行比较即可知道密码是否正确
crypto所涉及的加密方式有很多,建议将加密函数封装为一个模块,便于后期维护