书写技术成长之路

大话PHP SESSION

说起session,作为一名后台开发程序猿,无人不知无人不晓。其实开发以来,只知道个大概原理,这次要详细记录下来。

session的由来

说起session的由来就必须先从HTTP说起了,由于HTTP协议是无状态的,所以并不能识别这个请求每次是谁发送的, 比如你这次发请求往购物车里添加商品,然后你又添加一个商品,由于HTTP的无状态,所以根本不能识别还是你添加的, 它把每次请求都视为不同的,这样就不能记录用户相关的信息了,更别说现在做什么智能推荐等等了。

为了能记录这些状态,一些先驱,前辈便发明了session和cookie这对兄弟。当你第一次请求服务器的时候,就给你分配一个唯一的session_id, 在服务端保存这个session_id,并在你的浏览器设置cookie,比如这个cookie名叫SESSIONID。当你下次发送请求的时候浏览器就会自动带上这个cookie发送到服务器端,服务器端查找这个SESSIONID,如果找到就可以识别这个就是你了。比如你不登录也能往购物车里添加商品,每次就是根据这个SESSIONID来维护购物车的状态,当你登录了就自动把购物车里商品信息记录到你的用户下。还有你不登录的时候一些APP的智能推荐新闻等,即使你未登录,也会在客户端和服务端有一个唯一标识你信息的ID。

如何设置30天自动登录呢?

30天自动登录,以前想的就是你登录成功的时候,就用setcookie把过期时间设置为30天的时间。但是这个只是设置cookie的有效期,跟服务端的session有效期是两个独立的概念。比如你手动把浏览器的cookie清除了,就登录不上去了,这只是你浏览器的SESSIONID不存在才导致不能登录,并不是SESSION也失效了,你看到的未必是你看到的~。如果你能伪造之前的COOKIE并发送到服务器端,还是可以登录的,因为这个时候服务端的SESSION还是有效的,并没有被回收。

那么SESSION的30天有效期怎么设置呢?

首先不是setcookie那么简单的就解决了,当然setcookie设置30天的有效期是必要的,但是还要设置服务端session的有效期。 stackoverflow的大神是这么说的

  • session.gc_maxlifetime should be at least equal to the lifetime of this custom expiration handler (1800 in this example);

  • if you want to expire the session after 30 minutes of activity instead of after 30 minutes since start, you'll also need to use setcookie with an expire of time()+60*30 to keep the session cookie active.

大意是说你要用session.gc_maxlifetime来设置session的最大生命周期,超过设个时间就会被垃圾回收, 然后在你的程序里,session_start的时候要设置一个last_activity值,记录最后更新的时间,如果这个值还存在,并且距离当前小于30天的 就表面还有效,就更新最后的更新时间,否则就销毁这个sesion,以此来实现30天自动登录的功能。

闲扯

现在更多的使用JWT(Json Web Token)来做状态标识了,因为一下几点使得JWT更适合当今的开发

  • SESSION默认是使用文件存储的,当访问量大和数据量大的时候,这会成为性能瓶颈
  • SESSION在负载均衡的时候会比较麻烦,当然可以使用Redis,Memcache等来解决(也能解决上面的问题)
  • SESSION在前后端分离模式下就显得更不适用了
  • JWT直接保存相关用户信息,还可以使用签名来保证安全,不用服务端保存这些信息,节省了空间,也解决了SESSION的性能瓶颈问题

参考地址

https://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes

http://www.laruence.com/2012/01/10/2469.html