注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

snoopyxdy的博客

https://github.com/DoubleSpout

 
 
 

日志

 
 

客户端session vs 服务端session  

2014-06-10 22:32:54|  分类: node |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
session想来大家都不会陌生,session主要的作用就是用来记录用户状态,表明用户身份的,session的存储方式也有多样,最为传统的就是服务端保存session的内容,客户端浏览器cookie保存sessionid,服务端通过客户端每次http请求带上的cookie中的sessionid去找到对应此用户的session内容。当然我之前也发过一篇文章讲到过通过etag来做为sessionid,识别用户身份。相关文章链接:http://cnodejs.org/topic/5212d82d0a746c580b43d948

最近在做公司一个项目,我们用到了python的flask框架,一个轻量级,易上手的python web框架,有点类似nodejs中的expressjs,一些周边相关的模块集成的比expressjs好一些,题外话,写了阵python回来写node,代码那是各种整齐啊。
说重点,flask和我之前用过的其他框架有一点不同的是,它的session默认是完全保留在客户端浏览器中的,也就是说我往flask的session中写入数据,最终这些数据将会以json字符串的形式,经过base64编码写入到用户浏览器的cookie里,也就是说无须依赖第三方数据库保存session数据,也无需依赖文件来保存,这一点倒是挺有意思。

估计很多人要问我安全性问题了,session内容保存在客户端cookie,如何保证它的保密性、完整性和容量限制,保密性表示不被其他用户窥探,完整性表示不被恶意用户篡改,容量限制则表示cookie中必然无法保存过多的数据。

1、保密性,flask 这方面可以说是完全不设防,经过简单的base64编码,很容易就可以对它进行decode,然后看到其中的数据,不过话又说回来,session中本来记录的就是当前用户的一些相关身份信息和操作记录,就算被本用户看见又何妨,如果怕网络传输时被截获,那用户其他的一些 http 请求操作也照样被截获,无关乎客户端的cookie session设计

2、完整性,flask 利用开发者定义的一个私钥对数据进行简单的hash签名认证,所以我们会看到在 flask 保存在浏览器cookie中的session值,经过base64解码之后都是这样的:

{"userid":12345}.xxxxxxxxxxxxx

json字符串后面的xxxx就是利用开发人员定义的密钥对前面json字符串进行hash生成的签名,所以数据的完整性只要保证一个足够强大的密钥不被泄露和就行了。

3、容量限制,这点确实是cookie session的不足,因为客户端cookie是有容量限制的,不可能像使用第三方数据库保存session那样可以存放大量的数据,不过一般我们开发一些web站点,session在大部分情况下主要是用来表示用户身份,比如一个 userid,一个头像地址,或者一个nickname等,真正用户的一些其他信息还是要通过userid去数据库获取的。

所以在开发一些对session保存容量要求不大,但是并发量比较大,而且需要多机器,多进程服务的项目来说,客户端session无疑是一个即轻松又节约设备的方法,至少节约了1台redis服务器。

我在开发完这个 flask 项目后,想到了node也应该在npm上有这样一个包,可惜我搜了下npmjs.org,似乎没有找到特别雷同的cookie session store的包,于是本着重复造轮的思想,写了一个让nodejs也支持客户端 cookie session保存的package,client-session,项目地址:
安装发放:
npm install client-session

client-session包主要解决了nodejs多进程下内存session无法同步的问题,让吊丝们的1G内存vps也能够不开redis,多进程同步session数据;同时在flask仅利用base64将session内容编码的基础上,做了一个小的加解密方法,让数据看上去更加安全一些,仅是安全一些,还是尽量不要保存用户密码,银行账户信息在里面哦。

client-session对数据加解密,base64编码以及签名和签名验证都是通过c++插件完成,所以相对于纯js性能上可能有那么点优势(没做过测试,不能妄下定论啊),另外在我的压力测试中,利用expressjs框架,多进程使用client-session要比使用本机开启redis数据库存session,性能高出20%左右,测试数据详见项目地址,client-session使用方法也很简单,一个结合expressjs框架返回计数器的代码例子:

   var express = require('express');
    var path = require('path')
    var cs = require('client-session');
    var clientSession = cs('mysecretkey');
    var app = express();
    app.use(clientSession.connect());//调用client-session中间件
    app.get('/', function(req, res){
      var count = req.csession['count'];
      if(!count) count = 1;
      else count++;
      req.csession['count'] = count;
      //这边不想暴力的改掉express框架的res.send方法
//就劳烦开发人员手动调用一下csflash,毕竟1台redis服务器是省下了
      req.csflush(); 
      res.send(count.toString());
    });
    app.listen(8124);
    console.log('Server running at http://127.0.0.1:8124/');

利用ab命令:ab -c 500 -n 20000 http://192.168.150.3:8124/
压力测试内网的一台2cpu 6Gmen linux云主机

express + redis + 2 process session::
Requests per second:    380.54 [#/sec] (mean)

express + client-session +2 process session:
Requests per second: 492.25 [#/sec] (mean)

具体的client-session使用方法,详见项目github地址,有啥问题可以留言给我。

对于客户端session和服务端session的优劣特点,大家都明白了,最终如何选择还是看项目需求吧~

另外expressjs似乎没有在响应前触发的事件吧,比如:

res.on('beforeResponse', function(){
//do something
})


  评论这张
 
阅读(1041)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016