MENU

PHP 的 Session 与 Cookie

November 27, 2021 • Read: 1046 • PHP,编码

为什么需要会话控制技术?

​ HTTP是无状态协议,没有一个内建机制维护两个事物之间的状态。同一个用户请求两次HTTP请求时,HTTP协议不会认为这两次请求都来自同一个用户,会当成两个独立的请求来处理。也就没有办法保持用户的登陆状态,所以会话控制技术的核心思想是 允许客户端跟踪服务端做出的连续请求 ,从而完成登陆状态的保持。

Cookie: 服务器发送给客户端的片段信息, 存储在客户端浏览器的内存或硬盘中的一种技术。

  • 写Cookie: setcookie(name,value,expire,path,domain,secure)

    • name:Cookie名称,可以使用 'a[b]'
    • value:Cookie值
    • expire:Unix时间戳,以秒为单位,如果不设置,则在浏览器关闭时过期
    • path:有效服务器路径,设置为 '/' 时,对整个域名domain有效,如果设置为 '/foo/' ,则仅对domain中/foo/目录及其子目录有效(例如:/foo/ban/)
    • domain:Cookie的有效域名/子域名,设置成子域名(例如:'www.example.com' ),会使Cookie对这子域名和他的三级域名有效(例如:w2.www.example.com)。要让Cookie对整个域名有效,设置顶级域名就行了(例如:example.com)
  • 读取Cookie: $_COOKIE
  • 删除Cookie: setcookie(name,'',time()-1) ,把Cookie设为过期即可

Cookie优缺点:

优点: 存储在客户端不会浪费服务器资源

缺点: 由于数据存储在客户端,不建议将一些敏感重要的数据使用Cookie存储。客户端有权限禁用掉Cookie的使用。

Session: 将用户的数据 存储在服务器 当中,用户无法禁止掉Session使用,但 Session不是完全脱离Cookie的 。Session是通过服务器客户端Cookie带过来的SESSIONID来确定用户数据的,如果Cookie被禁用,需要通过URL传递SESSIONID的形式保存SESSION的状态。

Session的使用

  1. 开启Session: session_start()
  2. 使用Session: $_SESSION 直接操作SESSION数组就可以
  3. 清空Session: $_SESSION=[]$_SESSION = null
  4. 删除Session(包括文件和Cookie): session_destroy()

Session的配置 php.ini 文件

  • session.auto_start 是否自动开启Session
  • session.cookie_domain 设置Session的有效域名
  • session.cookie_lifetime 设置的cookie有效时间,是从创建了这个cookie时开始计算,不会因为操作而刷新
  • session.cookit_path 设置session有效服务器路径
  • session.name 存储在客户端的Cookit的名称,
  • session.save_path 设置session在服务器存储路径
  • session.use_cookies 是否使用Cookie传递session
  • session.use_trans_sid 是否允许SESSIONID通过URL明文传输
  • session.gc_probability 清理多少次垃圾
  • session.gc_divisor 每访问多少次
  • session.gc_maxlifetime 设置的session的最大生命周期
  • session.save_handler 设置存储方式,可以存储到Redis中或MySQL中,默认是'files'类型,即文件存储

Session垃圾回收机制

​ Session是存储在服务器上的,如果用户没有走退出程序而是直接关闭掉了浏览器,则Session文件会永久的保存在服务器上,时间长了会撑满内存,这个适合就需要使用Session的垃圾回收机制,大概流程是这样的:

  1. 当用户长时间没有再次访问Session,比如刷新、修改、添加等操作(时间根据:session.gc_maxlifetime设置的秒数,默认1440,PHP5默认1500),超过这个时间 则Session将会被设为过期的“垃圾文件”
  2. 当Session被设置为垃圾文件时,PHP每被请求设定次数 (次数根据: session.gc_divisor 设置的次数,默认1000),清除设定个数文件(session.gc_probability 默认是1次,也就是说每访问1000次清空一个过期文件),不建议把清除次数设置的特别小,会消耗服务器资源

优点: 数据存储在服务器,相比Cookie比较更安全。

缺点: 占用服务器资源,如果垃圾回收机制设置不合理,会撑满服务器硬盘。

Cookie被禁用时如何传递SESSIONID

<!-- 使用session_name()和session_id()传递 -->
<a href="<?php echo session_name().'='.session_id()?>">下一个页面</a>
<!-- 使用SID常量传递,SID比较智能,比较推荐使用这个-->
<!-- 在Cookie开启的时候,值为空,Cookie禁用的时候才会输出 -->
<a href="<?php echo SID?>">下一个页面</a>

Session存储共享(Redis/MySQL/Memcache)

​ 如果需要使用多台服务器的话,直接将Session存储到其中一台服务器的时候,可能下次访问的时候就是另一台服务器了,这种情况下Session因为不能共享的原因会导致用户的Session信息无法共享在其他的服务器上。这时需要使用 session_set_save_handler 设置用户自定义会话存储函数。