PHPSESSID 生成

生成规则是根据hash_func散列来生成的,相关的参数有:

- 客户端IP

- 当前时间(秒)

- 当前时间(微妙)

- PHP自带的随机数生产器

hash_func 是 phpinfo中的 session.hash_function 配置。如下:

; Select a hash function for use in generating session ids.
; Possible Values
;   0  (MD5 128 bits)
;   1  (SHA-1 160 bits)
; This option may also be set to the name of any hash function supported by
; the hash extension. A list of available hashes is returned by the hash_algos()
; function.
; http://php.net/session.hash-function
session.hash_function=0

 

PHPSESSID 示例

例如:访问米扑代理首页 https://proxy.mimvp.com ,查看 Cookie: PHPSESSID=01h0717afdteigg9nqn61vuek3; 

Request Headers 如下:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,pt;q=0.6
Cache-Control: no-cache
Connection: keep-alive
Cookie: PHPSESSID=01h0717afdteigg9nqn61vuek3; Hm_lvt_51e3cc975b346e7705d8c255164036b3=1578379811,1578564397,1578630437,1579153880; userinfo=MmzihmtvapW12cGE6Mzp7czoxMDoidXNlcl9lbWFpbCI7czozOToiTW16aWhtdHZhcFcxMmNITmhaRzFwYmtCdGFXMTJjQzVqYjIwTzBPIjtzOjg6InVzZXJfcHdkIjtzOjU3OiJNbXppaG10dmFwVzEyY0dWbU0yTTVPVGsxT1RSbE5XSXdabUk1TmpWbU56VTBZekV5WVRaak1EaGkiO3M6MTM6InVzZXJfcmVtZW1iZXIiO3M6MTk6Ik1temlobXR2YXBXMTJjREVPME8iO30O0O; Hm_lpvt_51e3cc975b346e7705d8c255164036b3=1579420011
DNT: 1
Host: localhost:8086
Pragma: no-cache
Referer: http://localhost:8086/sadmin/
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36

 

PHP session工作原理

以下以cookie传输PHPSESSID描述。

1. 客户端请求一个php的服务端地址。

2. 服务端收到请求,此次php脚本中包含session_start()。

3. 服务端会生成一个PHPSESSID。(默认session存储方式为session.save_handler=files,文件形式存储。生成的session文件名规则即为sess_PHPSESSID,session文件存在session.save_path中。)

4. 服务端响应首部Response Headers:Set-Cookie:PHPSESSID=37vjjasgjdv2ouk1uomhgqkv50; path=/。在客户端生成一个cookie保存此PHPSESSID。

5. 此时,客户端的cookie里面包含了PHPSESSID,之后客户端的每次请求首部Request Headers:Cookie:PHPSESSID=37vjjasgjdv2ouk1uomhgqkv50

6. 服务端之后每次接收到客户端的请求就都能根据这个PHPSESSID来找到服务端的session文件,通过对这个session文件的读写操作即实现了session的超全局变量属性。

如果客户端禁用了cookie,由于无法使用cookie传递PHPSESSID,那么客户端每次请求,服务端都会重新建立一个session文件,而无法通过通过PHPSESSID来重用session文件,所以session也就失效了。

这种情况可以设置session.use_trans_sid 来传输PHPSESSID,具体实现方式与cookie的区别就是将PHPSESSID通过HTTP的GET传输。每次请求的地址里面都会补全PHPSESSID参数”url?PHPSESSID=37vjjasgjdv2ouk1uomhgqkv50”来实现。详见米扑博客:PHP Session 与 Cookie 详解

 

PHP cli 模式通过session_id()使用session

官网说明

可以通过它来获取当前会话的PHPSESSID,也可以通过它来设置当前的会话PHPSESSID。

PHP cli模式下可以通过设置这个,达到使用session的目的,非常方便。

例如:vim test_php_session.php

<?php
// session_id('01h0717afdteigg9nqn61vuek3');
session_start();
$_SESSION[md5(rand(100,999))] = rand(100,999);
var_dump($_SESSION);

未使用session_id()的时候,在cli模式下运营此php脚本三次:

$ /usr/local/php/bin/php test_php_session.php
array(1) {
  ["3cec07e9ba5f5bb252d13f5f431e4bbb"]=>
  int(794)
}
$ /usr/local/php/bin/php test_php_session.php
array(1) {
  ["ff4d5fbbafdf976cfdc032e3bde78de5"]=>
  int(856)
}
$ /usr/local/php/bin/php test_php_session.php
array(1) {
  ["d240e3d38a8882ecad8633c8f9c78c9b"]=>
  int(668)
}

可以看到由于cli模式下没有传输PHPSESSID,所以每次都是一次性的随机生成和使用 session 文件,session没有生效。

查看下session文件:

$ cd /System/Volumes/Data/private/var/folders/wq/vgx37qxd0jjcmkry1y729k340000gn/T/
$ ls -l sess_*
-rw-------  1 homer  staff  39  1 19 15:33 sess_0ecf2f025d848553f12a564fcdc8718c
-rw-------  1 homer  staff  39  1 19 15:34 sess_74d0dd6eb98ec4281c10b310f3fd4da1
-rw-------  1 homer  staff  39  1 19 15:34 sess_ec5ee38e126e37df462f2bbe3eeb02dd

这三个session文件是我们三次cli执行生成的,三个session文件的内容如下:

$ more sess_0ecf2f025d848553f12a564fcdc8718c
3cec07e9ba5f5bb252d13f5f431e4bbb|i:794;
$
$ more sess_74d0dd6eb98ec4281c10b310f3fd4da1
ff4d5fbbafdf976cfdc032e3bde78de5|i:856;
$
$ more sess_ec5ee38e126e37df462f2bbe3eeb02dd
d240e3d38a8882ecad8633c8f9c78c9b|i:668;

 

首先,将之前的session文件删除掉

rm -f sess_*

然后,如果我们使用session_id(),为cli脚本设定固定的PHPSESSID

例如:vim test_php_session.php

<?php
    session_id('01h0717afdteigg9nqn61vuek3');
    session_start();
    $_SESSION[md5(rand(100,999))] = rand(100,999);
    var_dump($_SESSION);
?>

然后cli运行脚本三次:

$ /usr/local/php/bin/php test_php_session.php       
array(1) {
  ["274ad4786c3abca69fa097b85867d9a4"]=>
  int(472)
}
$ 
$ /usr/local/php/bin/php test_php_session.php 
array(2) {
  ["274ad4786c3abca69fa097b85867d9a4"]=>
  int(472)
  ["4c27cea8526af8cfee3be5e183ac9605"]=>
  int(797)
}
$ 
$ /usr/local/php/bin/php test_php_session.php 
array(3) {
  ["274ad4786c3abca69fa097b85867d9a4"]=>
  int(472)
  ["4c27cea8526af8cfee3be5e183ac9605"]=>
  int(797)
  ["01161aaa0b6d1345dd8fe4e481144d84"]=>
  int(122)
}

最后,查看下session文件,就只有一个我们设置的session文件

$ cd /System/Volumes/Data/private/var/folders/wq/vgx37qxd0jjcmkry1y729k340000gn/T/
yg-mac:T homer$ ll sess_*
-rw-------  1 homer  staff  117  1 19 15:52 sess_01h0717afdteigg9nqn61vuek3

session文件内容:

$ more sess_01h0717afdteigg9nqn61vuek3
274ad4786c3abca69fa097b85867d9a4|i:472;4c27cea8526af8cfee3be5e183ac9605|i:797;01161aaa0b6d1345dd8fe4e481144d84|i:122;

这样,在PHPcli模式下,session就可以使用了。

session_id()的作用,即为PHP脚本自己设定了PHPSESSID,而不需要传输PHPSESSID

另外,cli模式下,session可以使用,apache的ab测试,session也就可以使用了。

 

 

通过设置 PHPSESSID 保存到 cookie,实现免用户名密码登录

$cookieParams = session_get_cookie_params();
session_set_cookie_params(
    3600,// 设置sessionID在cookie中保存的时长
    BASE_DATA_PATH.'/session',
    $cookieParams['domain'],
    $cookieParams['secure']
);
session_regenerate_id(true);

说明:该方式存在安全风险,建议把member_id存到cookie再次进入的时候进行登陆操作。

 

 

ThinkPHP URL 自己带上参数 PHPSESSID

碰到个问题,ThinkPHP项目程序本地测试没问题,传到服务器后第一次访问,页面的所有URL会自己带上类似?PHPSESSID=28954583914413546c6e881cfa7c8117 这样的参数,再点击刷新下页面后访问才正常。

浏览器并没有禁止cookie,本地访问正常也证实了这点,第一猜想是服务器的环境配置与项目代码某些地方冲突所影响。

检测了服务器的关于cookie的配置对比本地的,发现session.use_trans_sid这个项的配值是不同的,本地关闭,服务器是开着的。

PHP中的会话在默认情况下是使用客户端的cookie来保存session_id的,所以当客户端的cookie出现问题的时 候就会影响会话了。其实会话不一定必须依赖cookie,当客户端的cookie被禁用或出现问题时,PHP会自动把session_id附加在URL 中,这样再通过 session_id就能跨页使用会话变量了。但这种自动的附加也是有一定条件的,首先,在php.ini文件中的 session.use_trans_sid = 1或者编译时打开了--enable-trans-sid选项,其次,运行PHP的服务器必须是UNIX/Linux系统,Windows操作系统不具备 此项功能。

上面的引用就说明了这点,在linux系统下,在session.use_trans_sid开启的时候,导致项目会自己加上PHPSESSID参数来达到跨页会话。

最后解决是:ini_set('session.use_trans_sid', 0); //在项目代码初始化的位置加入这句

其实还有个怀疑,可能项目某配置出现问题。待查。

Ps,这问题也反面教了件事,在处理跨页会话跨域会话的时候,session.use_trans_sid或许能起到奇效。

 

 

ThinkPHP PHPSESSID 过期问题

1、问题场景:

浏览器打开网页,停留N分钟,再次刷新网页,PHPSESSID变了,登陆的用户也就自然退出了

2、分析问题:

找不到导致PHPSESSID变的原因

session.cookie_lifetime = 0

例如:

ini_set('session.use_cookies', 1);     // 使用COOKIE保存SESSIONID的方式
ini_set('session.cookie_domain', 'proxy.mimvp.com');

3、讨论问题:

PHP 采用的是 ThinkPHP 框架 v3.23

ThinkPHP 官网http://www.thinkphp.cn

ThinkPHP 是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。

 

session一定要用 session_set_save_handler 重写.

其实你设定过期时间一年后,但是其他没有保存为一年后的用户还会触发session的gc,从而强制回收你的session.

<?php
    'SESSION_OPTIONS'=>array('type'=> 'db',     // session采用数据库保存       
    'expire'=>7200,     // session过期时间,如果不设就是php.ini中设置的默认值      
    ),  
    'SESSION_TABLE' =>'v4_session',     // 必须设置成这样,如果不加前缀就找不到数据表,这个需要注意
?>

两种方法重写:

1. 存储redis、mysql等数据库, 过期时间你自己控制.

2. 存储文件files,技巧是强制修改session文件的时间为未来的时间,这样其他用户触发gc后就没法回收你的session文件了.


session是跟随cookie存数据,问题是cookie这边sessid过期换掉了,而不是session过期

session.gc_maxlifetime = 1440; 指定最后一次访问后的 1440 秒失效

但是否真的失效,取决于 session.gc_probability 和 session.gc_pisor 比值(失效概率)

对于 ThinkPHP,你有 'expire'=>7200 那么应在最后一次访问的 7200 秒(2小时)后失效 如果不是这样,那就放弃 ThinkPHP

跟程序没关系,程序存到数据库的都是正常的。

7200是有效的是因为PHPSESSID 值失效(a变b),a在数据库里是存在,但b是不存在的,所以相当导致用户的整个session失效

 

服务器上session失效,网页刷新当然重新分配了一个sessionid啊

session.cookie_lifetime=0 指的是在浏览器关闭时删除cookie、session,除非手动删或者被其他软件强清了

不知道对不对,PHPSESSID 是根据cookie传到客户端,用来判断用户的唯一性,如果cookie设置0秒,会自动清空,客户端没有PHPSESSID,服务端当然会重新分配一个,所以就注销了。


服务器session没有失效,存的数据库。。。

是因为存在coookie 的 PHPSESSID 值变了,而这个phpsessid在数据库里是没数据的

对的,问题是系统配置是2个小时,有时候10分钟有时候1个小时PHPSESSID就被重新分配了(同一个页面一直刷新)

找不出原因 session和cookies那点事说难不难,说简单也不简单,整到完美磨合,俩合作完美无间要仔细研究下,不过封装好以后就省事了.

你看看你是不是session_id($_COOKIES['sess_id']);没有这样接管.

还有cookies的作用域问题,作用路径问题,查查setcookie参数你就知道了...

正常不会这样,既然tp(ThinkPHP)设置了7200实效,根据session.gc处理,只会在7200秒后执行清除

你可以检查是否有其他程序导致session实效。

之前做法是,把session保存在cookies,如果判断session失效但cookie没有实效,则把cookie复制入session处理。

已经找出问题

<?php 
    function session($name='',$value='') {            
    ini_set('session.gc_maxlifetime',   $name['expire']);            
    // ini_set('session.cookie_lifetime',  $name['expire']);}
?>

 

 

参考推荐:

PHP Session与Cookie详解

PHP中的Session和Cookie应用

爬虫突破网站封禁不能抓取的6种常见方法

curl 查看 HTTP Header 响应头信息

Linux curl 命令模拟 POST/GET 请求  (推荐

shell命令curl 检测代理是否可用          

PHP 模拟POST提交2种方法         

PHP 异步后台处理

米扑代理使用示例

Linux 命令大全 curl 命令