PHP 实现多网站共享用户SESSION 数据解决方案

news/2024/5/11 0:39:02/文章来源:https://blog.csdn.net/weixin_34413103/article/details/93974697

PHP 实现多网站共享用户SESSION 数据解决方案

来源URL:http://blog.csdn.net/dongdongzzcs/article/details/6906613

一、问题起源

稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享SESSION 数据的问题。

二、PHP SESSION 的工作原理

在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION,这样就会产生客户端的唯一标识 SESSION ID(此 ID 可通过函数 session_id() 获取/设置)。SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时,PHP 程序可以获知客户端的 SESSION ID;一种是将 SESSION ID 自动加入到 GET 的 URL 中,或者 POST 的表单中,默认情况下,变量名为 PHPSESSID;另一种是通过 COOKIE,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID。这里我们主要以 COOKIE 方式进行说明,因为应用比较广泛。

那么 SESSION 的数据保存在哪里呢?当然是在服务器端,但不是保存在内存中,而是保存在文件或数据库中。默认情况下,php.ini 中设置的 SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,而 SESSION 文件保存的目录由 session.save_path 指定,文件名以 sess_ 为前缀,后跟 SESSION ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的数据即是序列化之后的 SESSION 数据了。如果访问量大,可能产生的 SESSION 文件会比较多,这时可以设置分级目录进行 SESSION 文件的保存,效率会提高很多,设置方法为:session.save_path="N;/save_path",N 为分级的级数,save_path 为开始目录。当写入 SESSION 数据的时候,PHP 会获取到客户端的 SESSION_ID,然后根据这个 SESSION ID 到指定的 SESSION 文件保存目录中找到相应的 SESSION 文件,不存在则创建之,最后将数据序列化之后写入文件。读取 SESSION 数据是也是类似的操作流程,对读出来的数据需要进行解序列化,生成相应的 SESSION 变量。

三、多服务器共享 SESSION 的主要障碍及解决办法

通过了解 SESSION 的工作原理,我们可以发现,在默认情况下,各个服务器会各自分别对同一个客户端产生 SESSION ID,如对于同一个用户浏览器,A 服务器产生的 SESSION ID 是 30de1e9de3192ba6ce2992d27a1b6a0a,而 B 服务器生成的则是 c72665af28a8b14c0fe11afe3b59b51b。另外,PHP 的 SESSION 数据都是分别保存在本服务器的文件系统中。如下图所示:

 

确定了问题所在之后,就可以着手进行解决了。想要共享 SESSION 数据,那就必须实现两个目标:一个是各个服务器对同一个客户端产生的 SESSION ID 必须相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一个名为 PHPSESSID 的 COOKIE;另一个是 SESSION 数据的存储方式/位置必须保证各个服务器都能够访问到。简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共享服务器端的 SESSION 数据。

第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的,如www.aaa.com 的服务器是不能读写www.bbb.com 服务器设置的 COOKIE 的。这里我们所说的同一网站的服务器有其特殊性,那就是他们同属于同一个一级域,如:aaa.infor96.com 和www.infor96.com 都属于域 .infor96.com,那么我们就可以设置 COOKIE 的域为 .infor96.com,这样 aaa.infor96.com、www.infor96.com 等等都可以访问此 COOKIE。PHP 代码中的设置方法如下:

 

[php] view plain copy
  1. <?php ini_set('session.cookie_domain', '.infor96.com'); ?>    


 

这样各个服务器共享同一客户端 SESSION ID 的目的就达到了。

第二个目标的实现可以使用文件共享方式,如 NFS 方式,但设置、操作上有些复杂。我们可以参考先前所说的统一用户系统的方式,即使用数据库来保存 SESSION 数据,这样各个服务器就可以方便地访问同一个数据源,获取相同的 SESSION 数据了。

解决办法如下图所示:

四、代码实现

首先创建数据表,MySQL 的 SQL 语句如下:

 

[sql] view plain copy
  1. CREATE TABLE `sess` ( `sesskey` varchar(32) NOT NULL default '',  
  2.  `expiry` bigint(20) NOT NULL default '0',  
  3.  `data` longtext NOT NULL, PRIMARY KEY (`sesskey`),  
  4.  KEY `expiry` (`expiry`) )  
  5.  ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci  



 

sesskey 为 SESSION ID,expiry 为 SESSION 过期时间,data 用于保存 SESSION 数据。

默认情况下 SESSION 数据是以文件方式保存,想要使用数据库方式保存,就必须重新定义 SESSION 各个操作的处理函数。PHP 提供了session_set_save_handle() 函数,可以用此函数自定义 SESSION 的处理过程,当然首先要先将 session.save_handler 改成 user,可在 PHP 中进行设置:

 

[php] view plain copy
  1. <?php  session_module_name('user'); ?>    


 

接下来着重讲一下 session_set_save_handle() 函数,此函数有六个参数:

 

[php] view plain copy
  1. session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc )  


 

各个参数为各项操作的函数名,这些操作依次是:打开、关闭、读取、写入、销毁、垃圾回收。PHP 手册中有详细的例子,在这里我们使用 OO 的方式来实现这些操作,详细代码如下:

[php] view plaincopy
  1. <?php  
  2. define('MY_SESS_TIME', 3600);   //SESSION 生存时长  
  3. //类定义  
  4. class My_Sess  
  5.  {  
  6.       function init()  
  7.       {  
  8.          $domain = '.infor96.com';  
  9.          //不使用 GET/POST 变量方式  
  10.          ini_set('session.use_trans_sid',    0);  
  11.          //设置垃圾回收最大生存时间  
  12.          ini_set('session.gc_maxlifetime',   MY_SESS_TIME);  
  13.          //使用 COOKIE 保存 SESSION ID 的方式  
  14.          ini_set('session.use_cookies',      1);  
  15.         ini_set('session.cookie_path',      '/');  
  16.          //多主机共享保存 SESSION ID 的 COOKIE  
  17.          ini_set('session.cookie_domain',    $domain);  
  18.          //将 session.save_handler 设置为 user,而不是默认的 files  
  19.          session_module_name('user');  
  20.          //定义 SESSION 各项操作所对应的方法名:  
  21.          session_set_save_handler(  
  22.               array('My_Sess', 'open'),   //对应于静态方法 My_Sess::open(),下同。  
  23.              array('My_Sess', 'close'),  
  24.               array('My_Sess', 'read'),  
  25.               array('My_Sess', 'write'),  
  26.               array('My_Sess', 'destroy'),  
  27.               array('My_Sess', 'gc')  
  28.           );  
  29.       }   //end function  
  30.      function open($save_path, $session_name) {  
  31.           return true;  
  32.       }   //end function  
  33.      function close() {  
  34.           global $MY_SESS_CONN;  
  35.   
  36.           if ($MY_SESS_CONN) {    //关闭数据库连接  
  37.              $MY_SESS_CONN->Close();  
  38.           }  
  39.           return true;  
  40.       }   //end function  
  41.   
  42.      function read($sesskey) {  
  43.           global $MY_SESS_CONN;  
  44.   
  45.          $sql = 'SELECT data FROM sess WHERE sesskey=' . $MY_SESS_CONN->qstr($sesskey) . ' AND expiry>=' . time();  
  46.          $rs =& $MY_SESS_CONN->Execute($sql);  
  47.           if ($rs) {  
  48.               if ($rs->EOF) {  
  49.                   return '';  
  50.               } else {    //读取到对应于 SESSION ID 的 SESSION 数据  
  51.                  $v = $rs->fields[0];  
  52.                  $rs->Close();  
  53.                   return $v;  
  54.               }   //end if  
  55.          }   //end if  
  56.          return '';  
  57.       }   //end function  
  58.   
  59.      function write($sesskey, $data) {  
  60.           global $MY_SESS_CONN;  
  61.             
  62.         $qkey = $MY_SESS_CONN->qstr($sesskey);  
  63.          $expiry = time() + My_SESS_TIME;    //设置过期时间  
  64.             
  65.          //写入 SESSION  
  66.          $arr = array(  
  67.              'sesskey' => $qkey,  
  68.              'expiry'  => $expiry,  
  69.              'data'    => $data);  
  70.          $MY_SESS_CONN->Replace('sess', $arr, 'sesskey', $autoQuote = true);  
  71.           return true;  
  72.       }   //end function  
  73.   
  74.      function destroy($sesskey) {  
  75.          global $MY_SESS_CONN;  
  76.   
  77.         $sql = 'DELETE FROM sess WHERE sesskey=' . $MY_SESS_CONN->qstr($sesskey);  
  78.         $rs =& $MY_SESS_CONN->Execute($sql);  
  79.          return true;  
  80.      }   //end function  
  81.   
  82.     function gc($maxlifetime = null) {  
  83.           global $MY_SESS_CONN;  
  84.   
  85.          $sql = 'DELETE FROM sess WHERE expiry<' . time();  
  86.          $MY_SESS_CONN->Execute($sql);  
  87.          //由于经常性的对表 sess 做删除操作,容易产生碎片,  
  88.           //所以在垃圾回收中对该表进行优化操作。  
  89.          $sql = 'OPTIMIZE TABLE sess';  
  90.         $MY_SESS_CONN->Execute($sql);  
  91.           return true;  
  92.       }   //end function  
  93.  }   ///:~  
  94.   
  95.   
  96. //使用 ADOdb 作为数据库抽象层。  
  97.  require_once('adodb/adodb.inc.php');  
  98.  //数据库配置项,可放入配置文件中(如:config.inc.php)。  
  99.  $db_type = 'mysql';  
  100.  $db_host = '192.168.212.1';  
  101.  $db_user = 'sess_user';  
  102.  $db_pass = 'sess_pass';  
  103.  $db_name = 'sess_db';  
  104.  //创建数据库连接,这是一个全局变量。  
  105.  $GLOBALS['MY_SESS_CONN'] =& ADONewConnection($db_type);  
  106.  $GLOBALS['MY_SESS_CONN']->Connect( $db_host, $db_user, $db_pass, $db_name);  
  107.  //初始化 SESSION 设置,必须在 session_start() 之前运行!!  
  108.  My_Sess::init();  
  109.  ?>  

五、遗留问题

如果网站的访问量很大的话,SESSION 的读写会频繁地对数据库进行操作,这样效率就会明显降低。考虑到 SESSION 数据一般不会很大,可以尝试用 C/Java 写个多线程的程序,用 HASH 表保存 SESSION 数据,并通过 socket 通信进行数据读写,这样 SESSION 就保存在内存中,读写速度应该会快很多。另外还可以通过负载均衡来分担服务器负载。不过这些都只是我自己的一些想法和假设,并没有实践过

 

转载于:https://www.cnblogs.com/long613/p/8287410.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_701386.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么制作营销型网站才能有效提升优化效果?

中小企业建设网站大多数都是为了推广自身产品或品牌&#xff0c;但是&#xff0c;并非所有网站都能达到网络营销或推广的作用。在这个信息爆炸的时代&#xff0c;必须通过互联网传播&#xff0c;才能发挥网站应有的价值。那为什么要做营销型网站呢&#xff1f;从营销角度来讲&a…

一个母婴电子商务网站贝贝网的大数据平台及机器学习实践【转】

关键字&#xff1a;大数据平台、机器学习 贝贝网的主要产品是垂直的母婴类&#xff0c;母婴相对一般的电子商务网站有一些特点&#xff1a;第一个特点是商品周期短&#xff0c;在母婴网站上的商品&#xff0c;在线的时间不会超过5-7天&#xff0c;第二个是用户需求的变化快&…

django前端引用数据_「基于Python技术的智慧中医商业项目」Django前端网站篇-5.资讯的数据交互...

如果你对中医感兴趣欢迎留言讨论&#xff0c;觉得我的内容对你有帮助的话&#xff0c;能够请我喝一杯沪上阿姨不禁万分感谢。内容简介本章介绍Django搭建中医网站项目平台前端建设之资讯模块的数据交互的内容。其中由于代码量较大&#xff0c;因此部分模块代码举例说明&#xf…

干货 | NLP、知识图谱教程、书籍、网站、工具...(附资源链接)

来源&#xff1a;人工智能头条本文多资源&#xff0c;建议阅读收藏。本文整理了关于 NLP 与知识图谱的众多参考资源&#xff0c;涵盖内容与形式非常丰富。[ 导读 ]本文作者一年前整理了这份关于 NLP 与知识图谱的参考资源&#xff0c;涵盖内容与形式也是非常丰富&#xff0c;接…

干货收藏 | 计算机学习绝对不能错过的10大网站(内附网站链接)

作者&#xff1a;肖镇东本文共2071字&#xff0c;建议阅读5分钟。本文整理出大数据和人工智能领域最实用&#xff0c;质量最高的10大技术网站信息&#xff0c;既可以用于丰富技术知识&#xff0c;也可以用于学术研究。[ 导读 ]随着AI&#xff0c;大数据这些技术的快速发展&…

程序员放大招教你网站怎么做短信验证码防刷验证码机制-速码云

文章来源&#xff1a;http://www.4006026717.com 在我们开始发送了 短信验证码 的时候在前台中会出现一分钟的倒计时&#xff0c;进行了这个操作了之后&#xff0c;在这段时间之内&#xff0c;如果用户多次提交的话是无法发送请求的。这种的方法是最为经常使用的一种&#xff0…

Spring Boot 搭载属于你的网站框架(一)

Spring Boot 搭载你的网站框架&#xff08;本次demo演示 使用工具 idea&#xff09; 使用springboot优点&#xff0c;简单快速便捷&#xff0c;只需要管理好pom文件&#xff0c;构建一个新项目是非常快的。 而且内置tomcat&#xff0c;用命令 java -jar jar包路径 的形式启动网…

没想到,阿里工程师每天必刷的网站是......

阿里人每日必逛的神奇内网 阿里内外是阿里内部员工使用的企业运行与协作平台。它诞生于2013年&#xff0c;彼时只是一个门户和企业社交的入口。但经过3年发展&#xff0c;阿里内外实现了平台化运营&#xff0c;不仅接入众多阿里应用与系统&#xff0c;阿里的生态公司也开始享受…

如何成为SEO专家(10步指南)

如何成为SEO专家&#xff08;10步指南&#xff09; 您想了解如何增加流量并获得更高的关键字排名&#xff0c;从而为您的网站带来更多销售和收入吗&#xff1f;那么你应该学习有关SEO的一切知识并成为SEO专家。 拥有SEO专业知识并不是SEO专业人士的唯一特权。任何想要学习如何自…

linux+xampp搭建WordPress个人网站过程详解

建站准备 建站流程 搭建网站注意事项可以参考以下文章 如何从零开始拥有自己的网站&#xff1f;新手建站十大必知忠告超详细新手建站指南以及预算成本估计注册域名 我是在阿里云万网上注册的域名&#xff1a;注册域名详情地址 。不懂这一步的可以参考建站流程里面的几篇文章。 …

jQuery Mobile手机网站案例

jQuery Mobile手机网站案例 一、总结 一句话总结&#xff1a;jQuery Mobile是纯手机框架&#xff0c;和amazeui和bootstrap都可以做手机网站。 1、另一款文本编辑器&#xff1f; jd编辑器 二、jQuery Mobile手机网站案例 1、index.php 1 <?php 2 include common/config.php…

PrestaShop 网站后台配置(三)

转载请注明出处&#xff1a;http://www.cnblogs.com/zhong-dev/p/4942957.html 网店版本 v1.6这一篇文章主要介绍 前台显示模块 的调整1&#xff1a;top banner&#xff08;首页横幅&#xff09;如上图&#xff0c;这个是首页横幅展示&#xff0c;其实是一个模块。在后台的模块…

怎样将优酷网站下载的视频KUX转MP4格式

在休息之余&#xff0c;相信大多数人都会拿手机看电视剧听音乐之类的&#xff0c;最近拍了很多的新片子&#xff1a;《毒液&#xff1a;致命守护者》、《无名之辈》、《亡命救赎》《影》等等优质电影&#xff0c;但是很多的电影都只能在电影院观看的&#xff0c;如果不去电影院…

40 个科研学术网站,赶紧来收藏一波!

关注上方“深度学习技术前沿”&#xff0c;选择“星标公众号”&#xff0c;资源干货&#xff0c;第一时间送达&#xff01;来源&#xff1a;中外学术情报编译&#xff1a;程序员大白科研工作者每天日常莫过于看文献、做实验、写论文。人生最郁闷的事情不过于是导师说&#xff0…

百度搜索关键字如何排名?“网站SEO”告诉你答案

作者 | 哪吒来源 | 程序员小灰&#xff08;ID&#xff1a;chengxuyuanxiaohui&#xff09;前言什么是SEO呢&#xff1f;SEO是Search Engine Optimization&#xff0c;意为“搜索引擎优化”&#xff0c;一般简称为搜索优化。对于SEO的主要工作就是通过了解各类搜索引擎如何抓取互…

如何在网站上同步查看BCH数据

当涉及到数字货币网络和市场时&#xff0c;有很多数据和资料需要同步。对于比特币现金&#xff08;BCH&#xff09;来说&#xff0c;值得庆幸的是现在还有许多专用的BCH数据网站&#xff0c;这些网站可轻松理解网络统计数据和市场指标的直观表示。 在早期&#xff0c;很难找到…

如何在网站上同步查看BCH数据

当涉及到数字货币网络和市场时&#xff0c;有很多数据和资料需要同步。对于比特币现金&#xff08;BCH&#xff09;来说&#xff0c;值得庆幸的是现在还有许多专用的BCH数据网站&#xff0c;这些网站可轻松理解网络统计数据和市场指标的直观表示。 在早期&#xff0c;很难找到…

为你的网站使用paypal

原文地址&#xff1a;http://www.codeproject.com/aspnet/UsePayPalPaymentInASPNET.asp Introduction Those who create commercial sites are faced with the question, "How should it receive payments?" One of the most popular payment systems in the world…

TP5实现支付宝电脑网站支付学习笔记

这两天在公司做一个小型WEB项目,需要有支付功能。第一次做支付宝的支付&#xff0c;踩了点小坑&#xff0c;还算顺利。激动的我赶紧记下实现的流程。第一步当然是在支付宝开放平台申请公钥私钥APPID等&#xff0c;支付宝关官方文档都有详细介绍&#xff0c;这里就省略。申请完了…

视频直播网站开发千万不能忘的一个知识点

对于视频直播网站开发的技术人员来讲&#xff0c;音视频即时通讯技术是需要熟练掌握的。毕竟像直播这样重视互动和实时性的应用场景&#xff0c;即时通讯可以从中起到很大的配合作用。目前市面上有很多服务商所提供的SDK可以帮助实现这一技术&#xff0c;但是在选择哪一家服务商…