稍微大一点的网站,通常都会有不只一个服务器,每个服务器运行着不同的功能模块或者不同的子系统,他们使用不同的二级域名,比如www.a.com、i.a.com、bbs.a.com。而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个子系统中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在i.a.com登录之后,进入www.a.com时,仍然需要重新登录,基本的通行证的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION 数据的问题。
为了解决这个问题,我们采用将 SESSION 的数据保存数据库的方式。关于PHP SESSION的扫盲这里就不在累赘。在默认情况下,各个服务器会各自分别对同一个客户端产生 SESSION ID,如对于同一个用户浏览器,www.a.com系统产生的 SESSION ID 是a0211e9de3192ba6c22992d27a1b6a0a,而i.a.com生成的则是277003f262f0c366946a86a28ba431d8。另外,PHP 的 SESSION 数据都是分别保存在本服务器的文件系统中。
想要共享 SESSION 数据,那就必须实现两个目标:www.a.com和i.a.com所产生的SESSION ID相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一个名为 PHPSESSID 的 COOKIE;另一个是 SESSION 数据必须存放在一个各个系统都能访问到的地方。简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共享服务器端的 SESSION 数据。
第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的,如 www.a.com 的服务器是不能读写 www.b.com 服务器设置的 COOKIE 的。这里我们所说的同一网站的服务器有其特殊性,那就是他们同属于同一个一级域,如:www.a.com 和 i.a.com 都属于域 .a.com,那么我们就可以设置 COOKIE 的域为 .a.com,这样 www.a.com、i.aaa.com 等等都可以访问此 COOKIE。PHP 代码中的设置方法如下:
ini_set('session.cookie_domain', '.a.com');
这样各个系统共享同一客户端 SESSION ID 的目的就达到了,下面就是共享SESSION数据,我们就将SESSION数据放在数据库中,首先建立数据库表:
CREATE TABLE sessions ( session_id varchar(32) NOT NULL, session_last_access int(10) unsigned, session_data text, PRIMARY KEY (session_id)
session_id为主键,保存SESSION ID ,session_last_access是SESSION最后更新时间,session_data是SESSION数据。
PHP 提供了session_set_save_handle() 函数,可以用此函数自定义 SESSION 的处理过程,当然首先要先将 session.save_handler 改成 user,可在 PHP 中进行设置:
接下来着重讲一下 session_set_save_handle() 函数,此函数有六个参数:
session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc )
各个参数为各项操作的函数名,这些操作依次是:打开、关闭、读取、写入、销毁、垃圾回收。PHP 手册中有详细的例子,详细代码如下:
$gb_DBHOSTname = "127.0.0.1"; //主机的名称或是IP地址 $gb_DBname = "dbname"; //数据库名称 $gb_DBuser = "username"; //数据库用户名称 $gb_DBpass = "pwd"; //数据库密码 $gb_COOKIE_DOMAIN = '.a.com'; $SESS_DBH = ""; $SESS_LIFE = get_cfg_var("session.gc_maxlifetime"); //得到session的最大有效期。 session_id(); //不使用 GET/POST 变量方式 ini_set('session.use_trans_sid', 0); //设置垃圾回收最大生存时间 ini_set('session.gc_maxlifetime', 13600); //使用 COOKIE 保存 SESSION ID 的方式 ini_set('session.use_cookies', 1); ini_set('session.cookie_path', '/'); //多主机共享保存 SESSION ID 的 COOKIE ini_set("session.cookie_domain", $gb_COOKIE_DOMAIN); //将 session.save_handler 设置为 user,而不是默认的 files session_module_name('user'); function sess_open($save_path, $session_name) { global $gb_DBHOSTname, $gb_DBname, $gb_DBuser, $gb_DBpass, $SESS_DBH; if (!$SESS_DBH = mysql_pconnect($gb_DBHOSTname, $gb_DBuser, $gb_DBpass)) { die('MySQL Error'); } mysql_query("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary", $SESS_DBH); if (!mysql_select_db($gb_DBname, $SESS_DBH)) { die('MySQL Error'); } return true; } function sess_close() { global $SESS_DBH; //$SESS_DBH->Close(); return true; } function sess_read($key) { global $SESS_DBH, $SESS_LIFE; // var_dump($SESS_DBH); $qry = "select session_data from sessions where session_id = '$key' "; $qid = mysql_query($qry, $SESS_DBH); // var_dump($qid); if (list ($value) = mysql_fetch_row($qid)) { return $value; } return false; } function sess_write($key, $val) { global $SESS_DBH, $SESS_LIFE; $session_last_access = time(); $value = $val; $qry = "insert into sessions values('$key',$session_last_access,'$value')"; $qid = mysql_query($qry, $SESS_DBH); if (!$qid) { $qry = "update sessions set session_last_access=$session_last_access, session_data='$value' where session_id='$key' "; $qid = mysql_query($qry, $SESS_DBH); } return $qid; } function sess_destroy($key) { global $SESS_DBH; $qry = "delete from sessions where session_id = '$key'"; $qid = mysql_query($qry, $SESS_DBH); return $qid; } function sess_gc($maxlifetime) { global $SESS_DBH; $old = time() - $maxlifetime; $old = mysql_real_escape_string($old); $qry = "delete from sessions where session_last_access < " . $old; $qid = mysql_query($qry, $SESS_DBH); return mysql_affected_rows($SESS_DBH); } session_module_name(); session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc"); session_start();
相关推荐
解决springboot实现跨域session共享问题,防止sql注入。可以更有效的解决token问题,欢迎下载,有问题可以再评论下方留言,及时解答!!加群:687942640
iframe 跨域访问session问题解决方法
Spring Boot 使用 Redis 进行配置 Session 共享(Ajax 跨域) 源码下载。
NULL 博文链接:https://justcoding.iteye.com/blog/747398
主要介绍了PHP实现cookie跨域session共享的方法,结合实例形式分析了php操作cookie的有效期、跨域、session存储等相关操作技巧,需要的朋友可以参考下
更改配置文件,实现session的跨域共享,记住登录的状态
session共享
该文件可以通过代码实例,让你清楚的理解session和cookie的意思,当你明白了这点,你就可以设计出来单点登录功能,同一账号在同一时间只能登录一次功能。同时你可以通过ie、firefox去测试你对...在此共享,你值的拥有
class Session { //mysql的主机地址 const db_host = "localhost"; //需要第三方指定ip地址 //数据库用户名 const db_user = "root"; //需要第三方指定自己的用户名 //数据库密码 const db_pwd = ""; /...
跨域资源共享CORS协议介绍, cross-origin resource sharing layer
一个基于php的跨域提交伪造数据的东东,有待于改进!
因为cookie在跨域的情况下,浏览器根本不允许互相访问的限制,为了突破这个限制,所以有了以下这个实现方案,使用postmessage和localstorage进行数据跨域共享。 原理比较简单,但是遇到的坑也不少,这里梳理一下,做...
主要介绍了Ajax跨域Session和跨域访问的相关问题,以及需要注意的地方,这里推荐给大家
【ASP.NET编程知识】iframe跨域与session失效问题的解决办法.docx
常用跨域共用session的是登录模块,我相信很多开发的朋友的都遇到过,只需要一个地方登录,相关联的网站也是处于登录状态。两种情况:一种9streets.cn和a.9streets.cn之间,另一种是a.com b.com之间,这几天总结了...
遇到了HTTP、HTTPS协议下session共享解决cookie失效的问题,这里提供一个临时解决办法。 实现原理:把session id设置到本地的cookie。 如下: 复制代码 代码如下: $currentSessionID = session_id(); session_id($...
参考的官网上的sessions共享,调整对高版本的framework的适应,采用vs2015 。可直接采用生成的cmodel
何为跨域跨域session/cookie? 也就是第三方session/cookie。第一方session/cookie指的是访客当前访问的网站给访客的浏览器设置的seesion /cookie, 会被存储在访客的计算机上。第三方session/cookie指的是当前访问的...
tomcat服务器跨域需要的CorsFilter jar包文件tomcat服务器跨域需要的CorsFilter jar包文件tomcat服务器跨域需要的CorsFilter jar包文件
主要介绍了ThinkPHP框架实现session跨域问题的解决方法,需要的朋友可以参考下