自定义实现getCookie /setCookie方法
1. 原生实现
使用http实现服务时,处理cookie是从回调函数的request参数从请求头中获取cookie;
let cookies = querystring.parse(req.headers.cookie, "; ");
res.end(cookies['name']);
通过response参数设置cookie响应头。
res.setHeader('Set-Cookie', ['name=lyra', 'age=18']);
但是操作方法不符合用户的操作习惯。
2. 封装实现
可以通过封装方法实现符合用户习惯的getCookie/setCookie方法。
其中为了避免服务器返回的cookie被用户任意修改,可以将cookie进行签名,如果修改,则服务器端不识别修改后的cookie。
let http = require('http');
let querystring = require('querystring');
let signedCookie = function(value) {
// 将value通过密钥secret签名后输出base64格式的内容
return require('crypto').createHmac('sha256', 'secret')
// cookie将+/去除
.update(value.toString()).digest('base64').replace(/[+/]/g, '');
}
http.createServer(function(req, res) {
res.getCookie = function(name) {
let cookies = querystring.parse(req.headers.cookie, "; ");
if (cookies[name]) {
let [value, signedValue] = cookies[name].split('.');
if (signedValue) {// 获取加盐的内容需要进行校验
if (signedCookie(value) === signedValue) {
return value;
}
} else {
return cookies[name]
}
}
return '';
}
let arr = [];
res.setCookie = function(key, value, options) {
let optionsArr = [];
// 如果服务器端设置的cookie是要求签名的,则内容需要使用加盐算法处理
if(options.signed) {
value = value+ '.' + signedCookie(value);
}
optionsArr.push(`${key}=${value}`);
if(options.domain) {
optionsArr.push(`domain=${options.domain}`);
}
if(options.path) {
optionsArr.push(`path=${options.path}`);
}
if(options.maxAge) {
optionsArr.push(`max-age=${options.maxAge}`);
}
if(options.expires) {
optionsArr.push(`expires=${options.expires}`);
}
if(options.httpOnly) {
optionsArr.push(`httpOnly=${options.httpOnly}`);
}
arr.push(optionsArr.join('; '))
res.setHeader('Set-Cookie', arr);
}
if(req.url === '/read') {
// 使用设置后的方法可以逐条获取
res.end(res.getCookie('age'));
}
if(req.url === '/write') {
// 使用封装后的方法可以逐条设置
res.setCookie('name', 'lyra', {path: '/write', httpOnly: true});
// signed表示cookie需要要经过签名
res.setCookie('age', 18, {domain: '.lyra.cn', maxAge: 10, signed: true});
res.end('writted');
}
}).listen(3000);

浙公网安备 33010602011771号