cookie&session
Cookie
在web应用中,多个请求之间共享“用户会话”是非常必要的,但http协议是无状态的,而cookie则可以处理。
· 服务端向客户端发送cookie
· 客户端的浏览器把cookie保存
· 然后在每次请求浏览器都会将cookie发送到服务端
在HTML文档被发送之前,web服务器通过传送HTTP包文头中的Set-Cookie消息把一个cookie发送到用户的浏览器中。其中比较重要的属性有:
· name=value:键值对,可以设置要保存的key/value,注意这里的name不能和其他属性项的名字一样
· Expires:过期时间(秒),在设置的某个时间点后该cookie就会失效
· maxAge:最大失效时间(毫秒),设置在多少后失效
· secure:当secure为true时,cookie在http中是无效的,在https中才有效
· path:表示cookie影响到的路径,如path=/。如果路径不能匹配时,浏览器则不发送cookie
· httpOnly:是微软对cookie做的扩展。如果在cookie中设置了该属性,则通过程序(JS脚本、applet等)将无法读取到cookie信息,防止XSS攻击产生。
nodejs使用response.writeHead向客户端发送cookie。使用writeHead只能发送一次头部,即只能调用一次,且不能与response.render共存,否则会报错。
还可以使用response.setHeader
var http = require('http');
http.createServer(function(req,res){
if(req.url == '/write'){
//响应头 实体头 扩展头自定义头
var time = new Date(new Date().getTime() + 10*1000).toGMTString();
res.writeHead(200,{
'Set-Cookie':'age=6; path=/; Expires='+time
});
res.end('ok');
}else if(req.url == '/read'){
console.log(req.headers.cookie);
//第二次
res.end('hello');
}
}).listen(8080);
express中使用cookie
express在4.x版本之后,管理session和cookie等许多模块都不再直接包含在express中,而是需要单独下载安装相应模块。
cookieParser安装: npm install cookie-parser
var express = require('express');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser());
// req.headers.cookie= name=zfpx; age=6
app.get('/write', function (req, res) {
// 默认设置
//res.cookie('name','zfpx');
//设置域名 只有再次访问指定域名的时候客户端才会向服务器端发送cookie
//res.cookie('name','zfpx',{
// domain:'.zfpx.cn'.
//});
//指定路径.,只有当下次客户端 向服务器发送请求时,如果path=/read1的时候,才会向服务器发送,否则 不发送
/* res.cookie('name','zfpx',{
path:'/read1'
});*/
//指定有效期
res.cookie('name','zfpx',{
expires:new Date(Date.now()+10*1000),
maxAge:10*1000
});
res.end('ok');
});
app.get('/read',function(req,res){
console.log(req.cookies);
res.send(req.cookies);
});
app.get('/read1',function(req,res){
console.log(req.cookies);
res.send(req.cookies);
});
app.listen(80);
cookie实现登录逻辑
var express = require('express');
var cookieParser = require('cookie-parser');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
app.set('view engine','ejs');
app.set('views',path.resolve());
app.use(cookieParser());
function checkLogin(req,res,next){
if(req.cookies && req.cookies.username){
next();
}else{
res.redirect('/');
}
}
//进入登录页
app.get('/',function(req,res){
res.render('login',{});
});
// 登录
app.get('/login',function(req,res){
var username = req.query.username;
res.cookie('username',username);
//重定向,让客户端重向新求参数指定的路径
res.redirect('/user');
});
//用户主页
app.get('/user',checkLogin,function(req,res){
res.send(req.cookies.username);
});
app.listen(80);
session
session是一种记录客户端状态的机制,不同的是cookie保存在客户端浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该session中查找该客户的状态就可以了。
如果说cookie机制是通过检查客户身上的通行证来确定客户身份的话,那么session几只就是通过检查服务器上的客户明细表来确认客户身份。session相当于程序在服务器上建立了一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
两者的区别:
· cookie数据存放在客户的浏览器上,session数据放在服务器上。
· cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,而session就相对更安全
· session会在一定时间内保存在服务器上,当访问增多,会比较占用服务器的性能,而cookie就相对可以减轻服务器的性能压力
· 单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie。
tips:将登陆信息等重要信息存放在session,其他信息如果需要保留,可以放在cookie中。
express中使用session
与cookie一样需要单独的安装和引用模块 npm install express-session
主要方法就是session(options),其中options主要有:
· name:设置cookie中,保存session的字段名称,默认为connect.id
· store:session的存储方式,默认存放在内存中,也可以使用redis、mongodb等。express生态中都有相应模块的支持
· secret:通过设置的secret字符串,来计算hash值并放在cookie中,使产生的signedCookie防篡改
· cookie:设置存放session id的cookie的相关选项,默认为{default:{path:'/',httpOnly:true,secure:false,maxAge:null}}
· genid:产生一个新的session_id时,所使用的函数,默认使用uid2这个npm包
· rolling:每个请求都重新设置一个cookie,默认为false
· resave:即使session没有被修改,也保存session值,默认为true
· saveUninitialized:保存新创建但未修改的session
var express = require('express');
var session = require('express-session');
var app = express();
var sessions = {};
app.use(session({
secret: 'zf', //secret的值建议使用随机字符串
cookie: {maxAge: 60 * 1000 * 30}, // 过期时间(毫秒)
resave:true,//每次响应结束 的时候 都重新保存session
saveUninitialized:true //保存未初始化的session
}));
app.get('/', function (req, res) {
if (req.session.sign) {//检查用户是否已经登录
console.log(req.session);//打印session的值
res.send('welcome <strong>' + req.session.name + '</strong>, 欢迎你再次登录');
} else {
//因为session是借用cookie实现的,所以当设置session的时候,会自动设置cookie。第一次访问的时候,会生成一个sid
req.session.sign = true;
req.session.name = 'zf';
res.send('欢迎登陆!');
}
});
app.listen(80);
首先引入express-sesion,然后使用session方法返回的中间件,执行完该中间件后request就会有一个session属性,其值为对象。第一次访问“/”时session没有sign值,则会先给sign赋值。
由于使用session时会给cookie存一个sessionId(即加密后的connect.id),所以session是依赖于cookie的。
session的原理是第一次访问的时候,随机生成一个sid并生成一个sid对应的对象,然后把这个sid发送到浏览器端。下次客户端把sid带回服务器,从服务器上找到这个sid对应的对象就可以了。
原理如下
var express = require('express');
var app = express();
app.use(require('cookie-parser')());
//放在服务器端的客户明细表
var session = {};
app.get('/', function (req, res) {
//取出cookie中的sid
var sid = req.cookies.sid;
//如果有值的话就表示访问过了
if(sid){
//从服务器的session对象中取出当前客户端在服务器对应的session
var currentSession = session[sid];
//赋值
currentSession.mny = currentSession.mny-10;
res.send(''+currentSession.mny);
}else{
//生成新的sid
var newSid = Date.now()+''+Math.random();
session[newSid] = {mny:100};
//写入到客户端
res.setHeader('Set-Cookie','sid='+newSid);
res.send('新朋友');
}
});
app.listen(80);