Web框架系列:Session的实现原理

2017-02-10

  WEB应用都很依赖session这一功能。不少同学不明白session的原理,其实,session实现起来非常简单。HTTP协议是无状态了,每次访问一个资源,就发起一次连接,得倒资源后,就关闭了连接。浏览器和服务器就无法联系了。所以,服务器为了认证浏览器的身份,需要让浏览器携带一个独一无二的信令,其他人无法获取到,也没有办法猜测到,每次浏览器来访问自己的时候都带上这个信令,服务器判断这个信令是不是自己发出的,就可以知道浏览器是谁了。原理这就是这么简单。这个信令就是cookie了。
  session的依赖浏览器的cookie。cookie的生命周期是服务器设置的。我们想要的效果是,如果用户关闭浏览器,离开了电脑,别人就不能再启动浏览器,打开之前的页面进入的系统了。HTTP Response里的expires域可指定Cookie的生命周期。如果不设置expires或者max-age这个cookie默认是Session的,也就是关闭浏览器该cookie就消失了。就相当于与这个信令永远的从这个世界上消失了。但是,父短短并不知道用户已经下线,所以,在服务端一般需要对Session设置一个生存期限。比如Tomcat默认是30分钟。30分钟内没有携带这个信令的访问来到,就需要释放session,避免占用内存。那如何实现呢?
   Java有Tomcat这样的Web容器,Session管理工作由容器来完成,session一般也常驻内存。Tomcat中有常驻进程,可以在常驻进程里每一秒中就判断一下,看看每一个session的最后访问时间距离现在是否超过了30分钟,如果超过了,就释放session。
   PHP没有容器这个概念,没有常驻后台进程的,也就是没有办法由容器主动的释放session,需要Application自己来做这个工作。注意,框架也属于application的一部分。一般而言,都是框架来实现session的管理。在Laravel里,由session保护的资源和非session保护的资源就需要自己手动分开。那如何实现释放session呢?
  1,每一个资源访问,都去遍历一下session的容器,判断最后访问时间,超时的剔除。
  2,如果session实现方式是文件,debian、ubuntu采用的方式更加暴力,使用/etc/cron.d/php5,定时的删除文件即可
 如果使用OpenResty这样的程序来实现,session是常驻内存的,但是没有常驻进程,但一个nginx worker绑定一个VM,只能通过nginx提供的timer模块,定时的去访问LuaVM中的session数据,也可以达到更新的目的。

  不少网站都有“一周内免登录”这样的选项,就是改变了cookie的生命周期。让上次浏览器关闭时cookie不被清除。这也是一个不安全的选项。

 

  1. http://www.blogjava.net/persister/archive/2010/08/24/329838.html
  2. http://blog.chinaunix.net/uid-7374279-id-2057534.html
  3. http://www.phpthinking.com/archives/318
  4. http://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes
  5. http://stackoverflow.com/questions/654310/cleanup-php-session-files
    http://stackoverflow.com/questions/7842963/memcachephp-session-tuning-how-does-memcache-expire-keys
如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)