Server端nodejs操作cookie
Cookie、session使用时的局限
redis的使用(nodejs连接redis-封装工具函数)
Server端nodejs操作cookie
查看cookie
修改cookie
实现登录验证
1、解析cookie
//解析cookie
const cookieStr = req.headers.cookie || '';
//登录验证测试
if(method === 'GET'&& path === '/api/user/login-test'){
if(req.cookie.username){
return Promise.resolve( new SuccessModel('登陆成功'));
}else{
return Promise.resolve( new ErrorModel('登陆失败'));
}
}
path=/代表cookie生效目录,’/’代表根目录,整个网站都生效
res.setHeader('Set-Cookie',`username=${loginData.username};path=/`)
Cookie相关的Http头
有 两个Http头部和Cookie有关:Set-Cookie和Cookie。
Set-Cookie由服务器发送,它包含在响应请求的头部中。它用于在客户端创建一个Cookie
Cookie头由客户端发送,包含在HTTP请求的头部中。注意,只有cookie的domain和path与请求的URL匹配才会发送这个cookie。
expires=<date>: 设置cookie的有效期,如果cookie超过date所表示的日期时,cookie将失效。
如果没有设置这个选项,那么cookie将在浏览器关闭时失效。
注意:date是格林威治时间(GMT),使用如下格式表示:
如何防止前端修改cookie:添加httpoply
httpOnly
res.setHeader('Set-Cookie',`username=${loginData.username};path=/;httpOnly`)
设置完效果
前端无法更改
问题:拼接cookie时会自动在分号后添加空格
解决:trim()
设置过期时间
expires=${getCookieExpires()
res.setHeader('Set-Cookie',`username=${loginData.username};path=/;httpOnly;expires=${getCookieExpires()}`)
cookie问题
会暴露传递参数
大小限制
如何解决:不传递username,存储userid,server端对应username
解决方案:session,即server端存储客户信息
//解析session
let needSetCookie = false;
let userId = req.cookie.userid
if(userId){
if(!SESSION_DATA[userId]){
SESSION_DATA[userId] = {}
}
}else{
needSetCookie = true;
userId = `${Date.now()}+${Math.random()}`;
SESSION_DATA[userId] = {}
}
req.sesssion = SESSION_DATA[userId];
if(needSetCookie){
res.setHeader('Set-Cookie',`userId=${userData.userId};path=/;httpOnly;expires=${getCookieExpires()}`);
}
//登录验证测试
if(method === 'GET'&& path === '/api/user/login-test'){
if(req.session.username){
// res.setHeader('Set-Cookie',`username=${loginData.username};path=/;httpOnly;expires=${getCookieExpires()}`)
return Promise.resolve( new SuccessModel(
{session:req.session}
));
}else{
return Promise.resolve( new ErrorModel('尚未登录'));
}
}
当前代码中使用Session的问题
目前session是js变量,放在nodejs进程内存中
第一,进程内存有限,访问量过大,内存暴增怎么办?(操作系统会限制一个进程的最大可用内存)
第二,正式上线后运行是多进程,进程之间内存无法共享
解决方案redis
Webserver最常用的缓存数据库,数据存放在内存中
相比于mysql,访问速度快
但是成本更高,可存储的数据量更小
Redis安装
教程地址:https://www.runoob.com/redis/redis-install.html
Redis使用
打开一个 cmd 窗口 使用 cd 命令切换目录到 C:\redis 运行:
redis-server.exe redis.windows.conf
这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。
切换到 redis 目录下运行:
redis-cli.exe -h 127.0.0.1 -p 6379
设置键值对:
set myKey abc
取出键值对:
get myKey
删除键值对
del mykey
查看所有键
keys *
redis demo
新建redis-test文件夹
npm i redis --save
报错
Error: Redis connection to 127.0.0.1:6739 failed - connect ECONNREFUSED 127.0.0.1:6739
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1106:14)
重启解决了……
最终代码
// const redis = require('redis');
// //创建客户端
// const redisClient = redis.createClient(6739,'127.0.0.1');
// redisClient.on('error',err=>{
// console.error(err);
// });
// //测试
// redisClient.set('myname','zhangsan',redis.print);
// redisClient.get('myname',(err,val)=>{
// if(err){
// console.error(err);
// return
// }
// console.log('val',val);
// //退出
// redisClient.quit();
// });
const redis = require("redis");
// //创建客户端
const redisClient = redis.createClient(6379,'127.0.0.1');
redisClient.on("error",(err)=>{
console.error(err);
})
redisClient.set('myname','zhangsan',redis.print);
redisClient.get('myname',(err,val)=>{
if(err){
console.error(4);
console.error(err);
return
}
console.log('val',val);
redisClient.quit();
});
控制台打印
Nodejs连接redis-封装工具函数
配置连接redis参数
这段代码逻辑很好
const redis =require("redis");
const {REDIS_CONF} = require("../conf/db");
//创建客服端
const redisClient = redis.createClient(REDIS_CONF.port,REDIS_CONF.host);
redisClient.on("error",(err)=>{
console.error(err);
});
function set(key,val){
if(typeof val === 'object'){
val = JSON.stringify(val);
}
redisClient.set(key,val,redis.print);
}
function get(key){
const promise = new Promise((resolve,reject)=>{
redisClient.get(key,(err,val)=>{
if(err){
reject(err)
return
}
// resolve(val)
if(val === null){
resolve(null)
return
}
try{
resolve(
JSON.parse(val)
)
}catch(ex){
resolve(val)
}
});
})
return promise
}
module.exports = {
set,
get
}