标签:evel 另一个 str 演示 Nid 支持 建立 浏览器 启动
使用过几种Web App开发语言和框架,都会接触到Session的概念。即使是一个简单站点访问计数的功能,也常常使用Session来实现的。其他常用的领域还有购物车,登录用户等。但是,对Session一直是一知半解,知其然而不知其所以然。
在认真的研究了HTTP协议,以及nodejs开发栈的express和express-session后,我终于比较有把握深入浅出的说清楚Session了,也算是满足了多年来开发过程中,常常浮现的对Session的好奇心吧。
本文使用nodejs v9.5.0作为技术验证工具。阅读本文前需要了解基础的HTTP知识和Cookie知识。详细需要参考rfc6265,或者阅读《HTTP小书》的最后一章。
用户在网站的一组相互关联的的请求和响应,就是一次会话。简而言之是这样的:
比如一个最简单的nodejs HTTP程序:
var http = require(‘http‘)
http.createServer(function(req,res){
res.end(‘hello‘)
}).listen(3000)
每个请求都会进入到此处理函数:function(req,res){res.end(‘hello‘) }
,在此函数内获得请求,处理响应,完成后发给客户端,就是一次访问。通过浏览器的developer tools,可以看到此次会话的请求内容和响应内容。
以站点计数应用为案例来说明的话,就是这些来自于同样访问者的多次访问,都可以获得当前站点的访问计数。
我们从一个案例开始引入会话的概念。当我们需要访问站点计数一类的功能时,我们希望用户访问此站点时:
此种情况下,我们需要有一个地方存储当前计数,这样才能在同一个客户在此访问时,可以取出当前计数,加一后返回给客户。当然也因此需要识别此用户(浏览器),为每个用户单独计数。就是说,不同的用户访问时,需要去取对应用户的当前计数。
识别客户的问题,常用的方法就是使用Cookie。Cookie是HTTP协议的一部分。HTTP可以通过头字段Set-Cookie为来访客户做一个标记,这个标记常常就是一个ID,下一次访问此站点时,HTTP会通过Cookie头字段,发送此ID到站点,由此站点知道此客户的身份和这个身份关联的状态信息,比如当前访问计数,或者此身份当前的购物车的内容等等。
识别了客户后,就可以在Web服务器内,为此客户建立它的独特的状态信息。
基于nodejs HTTP模块,我们实现一个极为简单的Session服务。只是为了展示概念,而不是为了实用的目的。此服务可以实现一个共享于同一站点的多次访问的req.session变量,此变量为一个对象,可以在此变量内写入新的成员,或者修改现存的成员变量的值,每次访问后会保存req.session,以便下次访问可以得到当前的值:
var http = require(‘http‘)
var sessionkey = "sessionkey3"
http.createServer(function(req,res){
if (req.url =="/"){
session(req,res)
req.session.count = (req.session.count+1) || 1
res.end(‘hi‘+req.session.count)
}else
res.end(‘‘)
}).listen(3000)
console.log(‘listen on 3000‘)
function session(req,res){
if (req.session)
return
var answer ,id
if(isSessionOk(req)){
id = getCookie(req)
answer = getSessionById(id)
}else{
answer= {}
id = createSession(answer)
setCookie(res,id)
}
req.session = answer
res.on(‘finish‘, function() {
saveSession(id,req.session)
});
}
function hasCookie(req){
return (getCookie(req)!=‘‘)
}
function getCookie(req){
try{
var c = req.headers[‘cookie‘]
var arr = c.split(‘;‘)
for (var i = 0; i < arr.length; i++) {
var kv = arr[i]
var a = kv.split(‘=‘)
if (a[0].trim() == sessionkey)
return a[1]
}
}catch(error){
return ‘‘
}
return ‘‘
}
function setCookie(res,id){
res.setHeader("set-cookie",sessionkey +"="+id)
}
var sessions = {}
var sid = 0
function getSessionById(sid){
return sessions[sid]
}
function getSessionByReq(req){
var sid = getCookie(req)
return sessions[sid]
}
function createSession(session){
sessions[sid++,session]
return sid
}
function saveSession(sid,session){
sessions[sid] = session
}
function isSessionOk(req){
return hasCookie(req) && getSessionByReq(req) !== undefined
}
程序代码比较简单,读者可以保持它到index.js,然后执行此程序,验证概念:
node index.js
然后,启动chrome,访问站点localhost:3000
,然后多次刷新,你可以看到每次刷新,返回的访问次数逐步累加。在打开另一个浏览器,比如safari,在此访问此站点,你会发现返回的访问计数从1开始,另外计数。因为是两个不同的浏览器内器,这就保证的它们是不同的访问客户,在站点内的代码,会区别两者,分别记录它们的状态信息。
代码使用了HTTP Cookie,基本算法很简单:
可能大家看到sessionkey这个变量,感觉有些莫名其妙。原因是每次cookie发送,同样的站点可能有多个框架需要使用此cookie头字段,比如php,aspx,jsp等都是需要使用了,为了好像不要冲突,大家各自使用cookie头字段内各自的key/value对即可。比如php的key默认是phpsessid,express-session默认的是connect.sid。
此代码演示了最基础的Session的概念,但是远远不是一个可用的模块,想要真实世界中使用的Session模块,可以考虑express-session。
实现一个真正可以的会话,还需要考虑很多问题:
标签:evel 另一个 str 演示 Nid 支持 建立 浏览器 启动
原文地址:https://www.cnblogs.com/kkdn/p/8963268.html