客户端浏览器和服务器之间通讯使用的http协议是一种无状态的协议,在它看来,客户端发起的每一个请求都是独立、没有关联的。然而,在实际的Web应用开发中,服务器却常常须要根据用户以往的一些状态或数据对请求作出相应的应答,因此须要记录用户的某些状态或数据。Session就是用于保持客户端请求和服务器应答之间的上下文联系,本文主要介绍PHP的Session机制。php
PHP的Session机制的工做过程大体是这样子的:当客户端浏览器向服务器发起一个请求的时候,服务器会检查请求数据包头部中的“Cookie”字段是否包含名称为session.name的变量(session.name是PHP的配置文件php.ini中的一个配置项,用于配置服务器使用的session的名称,默认为“PHPSESSID”),该变量的值即为sessionid,即:$_COOKIE[session.name]=sessionid。若不存在,PHP会在session.save_path配置的路径目录下生成一个文件(session.save_path也是PHP的配置文件php.ini中的一个配置项,配置服务器session文件放置的位置),同时生成一个sessionid,这个文件的名称即为“sess_”和sessionid拼凑而成。而后在发送给浏览器的数据包头部中的Set-Cookie字段中指定session的名称和对应的sessionid,浏览器则根据该字段的信息在内存中建立一个Cookie,严格来讲叫SessionCookie。下一次浏览器再访问服务器的时候便会在数据包头部的Cookie字段中加入该Cookie。若服务器发现浏览器请求包头部中“Cookie”字段包含了名为session.name的sessionid,就会根据该sessionid到session.save_path指定的路径下找到名称为“sess_”+sessionid的文件,对文件进行读取或写入操做,开始了和客户端之间的会话。数据库
因为SessionCookie是存在于浏览器内存中的,因此当浏览器关闭的时候,原来的SessionCookie也就消失了,下一次访问同一个服务器须要再次建立session文件和Cookie,固然也有一些cookie是存储在客户端硬盘中的,即便关闭了浏览器,下一次打开浏览器访问相同网站的时候仍是可使用这个cookie。当客户端的cookie过时以后,服务器中原来的session文件也就没有用处了。在PHP的配置文件php.ini中,使用配置项“session.gc_maxlifetime”来设置session文件的生存期,超过这个时间期限的文件数据都将被视为垃圾,并由垃圾回收程序处理。垃圾回收程序是在会话初始化时启动的,但并非每一次都会启动,是有必定几率的,PHP配置文件中使用“session.gc_probability”和“session.gc_divisor”这两个配置项来设置这个几率,计算公式为:session.gc_probability / session.gc_divisor。浏览器
以上讲述的是使用Cookie来存储sessionid的方法,这也是PHP默认的存储sessionid的方法。当客户端的Cookie出现问题的时候,如:用户设置浏览器禁用cookie,session就会受到影响了。不过咱们能够经过其余方法来存储sessionid,主要有如下三种方法:安全
1. 设置文件php.ini中的session.use_trans_sid = 1,可让PHP自动跨页传递sessionid(PHP会自动把sessionid附着在URL末尾)。服务器
2. 手动经过URL传值,或经过隐藏表单字段传递sessionid。cookie
3. 使用文件、数据库等形式保存sessionid,在跨页过程当中手动调用。session
注意,方法一配置session.use_trans_sid=1的同时也要配置session.use_only_cookies=0,不然客户端禁用了Cookie以后即便置session.use_trans_sid=1,session仍是没法使用。函数
在方法二中,第一次调用session_start()函数时,PHP会建立一个session文件并产生一个sessionid,能够经过session_id()函数得到该sessionid,将sessionid拼接在url后面经过get方法传递(这种方法是存在很大的安全问题的),或者将sessionid做为表单的隐藏字段使用post方法传递,而后在下一个页面中能够把传过来的sessionid做为参数传递给PHP的session_id()函数,指定要读写的session文件,而后调用session_start()函数启动session会话,接下来就能够对session文件进行读取操做了。post
必须说明的是,PHP的Session机制并非绝对安全的,攻击者若是能经过必定手段劫持、或者猜想出某个合法用户的sessionid,那么属于这个用户的session数据都将暴露。因此,开发者应该设计一些方案来防护攻击者的攻击,提升Session机制的安全性,下面提供了一种利用请求数据包头部中的一些字段信息来增强Session安全性的方案思路。网站
将头部字段“User-Agent”和sessionid组合起来加密生成一个token,而且让客户端在后续的请求中携带这个token。为了更加保险,可以使用两种不一样的数据传递方式来 分别传递sessionid和token,例如,经过cookie传递sessionid,经过get方式传递token。