稍微大一点的网站,通常都会有不只一个服务器,每个服务器运行着不同的功能模块或者不同的子系统,他们使用不同的二级域名,比如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 代码中的设置方法如下:

1 ini_set('session.cookie_domain''.a.com');

这样各个系统共享同一客户端 SESSION ID 的目的就达到了,下面就是共享SESSION数据,我们就将SESSION数据放在数据库中,首先建立数据库表:

1 CREATE TABLE sessions (
2  session_id varchar(32) NOT NULL,
3  session_last_access int(10) unsigned,
4  session_data text,
5  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 手册中有详细的例子,详细代码如下:

01 $gb_DBHOSTname "127.0.0.1"//主机的名称或是IP地址
02 $gb_DBname "dbname"//数据库名称
03 $gb_DBuser "username"//数据库用户名称
04 $gb_DBpass "pwd"//数据库密码
05 $gb_COOKIE_DOMAIN '.a.com';
06 $SESS_DBH "";
07 $SESS_LIFE = get_cfg_var("session.gc_maxlifetime"); //得到session的最大有效期。
08  session_id(); //不使用 GET/POST 变量方式
09 ini_set('session.use_trans_sid', 0); //设置垃圾回收最大生存时间
10 ini_set('session.gc_maxlifetime', 13600); //使用 COOKIE 保存 SESSION ID 的方式
11 ini_set('session.use_cookies', 1);
12 ini_set('session.cookie_path''/'); //多主机共享保存 SESSION ID 的 COOKIE
13 ini_set("session.cookie_domain"$gb_COOKIE_DOMAIN);
14 //将 session.save_handler 设置为 user,而不是默认的 files session_module_name('user');
15 function sess_open($save_path$session_name) {
16     global $gb_DBHOSTname$gb_DBname$gb_DBuser$gb_DBpass$SESS_DBH;
17     if (!$SESS_DBH = mysql_pconnect($gb_DBHOSTname$gb_DBuser$gb_DBpass)) {
18         die('MySQL Error');
19     }
20     mysql_query("SET character_set_connection=utf8, character_set_results=utf8, character_set_client=binary"$SESS_DBH);
21     if (!mysql_select_db($gb_DBname$SESS_DBH)) {
22         die('MySQL Error');
23     }
24     return true;
25 }
26  
27 function sess_close() {
28     global $SESS_DBH;
29     //$SESS_DBH->Close();
30     return true;
31 }
32  
33 function sess_read($key) {
34     global $SESS_DBH$SESS_LIFE;
35 //      var_dump($SESS_DBH);
36     $qry "select session_data from sessions where session_id = '$key' ";
37     $qid = mysql_query($qry$SESS_DBH);
38 //      var_dump($qid);
39     if (list ($value) = mysql_fetch_row($qid)) {
40         return $value;
41     }
42     return false;
43 }
44  
45 function sess_write($key$val) {
46     global $SESS_DBH$SESS_LIFE;
47     $session_last_access = time();
48     $value $val;
49     $qry "insert into  sessions values('$key',$session_last_access,'$value')";
50     $qid = mysql_query($qry$SESS_DBH);
51     if (!$qid) {
52         $qry "update sessions set session_last_access=$session_last_access, session_data='$value' where session_id='$key' ";
53         $qid = mysql_query($qry$SESS_DBH);
54     }
55     return $qid;
56 }
57  
58 function sess_destroy($key) {
59     global $SESS_DBH;
60     $qry "delete from sessions where session_id = '$key'";
61     $qid = mysql_query($qry$SESS_DBH);
62     return $qid;
63 }
64  
65 function sess_gc($maxlifetime) {
66     global $SESS_DBH;
67     $old = time() - $maxlifetime;
68     $old = mysql_real_escape_string($old);
69     $qry "delete from sessions where session_last_access < " $old;
70     $qid = mysql_query($qry$SESS_DBH);
71     return mysql_affected_rows($SESS_DBH);
72 }
73 session_module_name();
74 session_set_save_handler("sess_open""sess_close""sess_read""sess_write","sess_destroy""sess_gc");
75 session_start();

php实现SESSION跨域的更多相关文章

  1. php SESSION跨域问题

    这段时间随着项目功能的扩展,慢慢接触到了跨域方面的知识,遇到的更多的问题也是前端与后端交互的时候跨域问题.关于js跨域的问题我会在其他分类里面写.这里记录我今天遇到的php session跨域问题 当 ...

  2. session跨域共享解决方案

    要让session跨域共享,需要解决三个问题: 1.通过什么方法来传递session_id? 2.通过什么方法来保存session信息? 3.通过什么方法来进行跨域? 一.传递session_id有4 ...

  3. thinkphp中session跨域问题

    问题描述 <thinkphp实现短信验证注册>中,小编不止记录了短信验证码的实现方法,同时还记录了图片验证码的实现方法. 本地使用,一切正常:后端项目和前端项目都部署到服务器,一切正常:后 ...

  4. 谈谈我的session跨域处理方法

    情景:公司的一个网站有一个模块(测试模块)需要单独用另外的一个域名(www.btest.com)去访问,即网站需要用两个不同的域名去访问,如首页(www.abc.com)和测试模块(www.xyz.c ...

  5. 【分布式系列】session跨域及单点登录解决方案

    Cookie机制 Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息. ...

  6. 使用Spring Session和Redis解决分布式Session跨域共享问题

    http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题

  7. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  8. sso单点登录的入门(Session跨域、Spring-Session共享)

    1.单点登录,就是多系统,单一位置登录,实现多系统同时登录的一种技术.单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的. 区分与三方登录(第三方登录) ,三方登录:某系统,使用其他系统 ...

  9. thinkphp session 跨域问题解决方案

    session 跨域,困扰我好几天,今天终于弄明白了! 不管是thinkphp ,还是本身的php 其实都要设置session.cookie_domain 设置好,就OK了 在thinkphp 里,在 ...

  10. java:sso(单点登录(single sign on),jsp文件动静态导入方式,session跨域)

    1.jsp文件导入: 2.session跨域: 3.sso(单点登录(single sign on): sso Maven Webapp: LoginController.java: package ...

随机推荐

  1. Java经典实例:正则表达式,找到匹配的文本

    import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by Frank */ public cla ...

  2. get()和post()方法编码的区别

    在做ssh搭建的框架中,在后台条件查询的时候,组合查询传到后台的值一直是乱码,其中在form表单中必须要加上method,这一点是肯定的,但是加上了提交的方式之后,会出现如下问题: 如果使用get方法 ...

  3. 我开发 wangEditor-mobile 的故事

    wangEditor-mobile 是一款适用于手机.手指操作的富文本编辑器,wangEditor-mobile 官网    1. 写在前面 其实,我一开始并没有想做什么手机端操作的富文本编辑器. w ...

  4. bootbox.js

    bootbox:一个弹出框插件,官网看一下例子就好了:http://bootboxjs.com/examples.html 目前来说应该只要调用bootbox.js就可以了,没有css的问题 1.有最 ...

  5. Strip JS – 低侵入,响应式的 Lightbox 效果

    Strip  是一个灯箱效果插件,显示的时候只会覆盖部分的页面,这使得侵扰程度较低,并留出了空间与页面上的大屏幕,同时给予小型移动设备上的经典灯箱体验.Strp JS 基于 jQuery 库实现,支持 ...

  6. Slick – 这是你需要的最后一款 jQuery 传送带插件

    slick 是一款完全响应式的 jQuery 传送带插件,能够根据容器自动适应宽度.在现代浏览器中会使用 CSS3 来实现特殊效果,可以使用扩展方法对项目进行添加.删除和过滤.这是你需要的最后一款 j ...

  7. 为Titanium创建自己的安卓推送模块

    在手机应用中,推送是一个非常重要的功能.相对来说ios应用的推送功能很容易做,因为它统一都是用苹果的APNS服务实现的.但安卓这边就比较混乱了,虽然谷歌也推出了类似苹果的官方推送服务,但由于谷歌的服务 ...

  8. CodeIgniter_2 路由中定义伪静态 直接映射到相关的控制器

    某些情况下 隐藏路径信息 使用伪静态定义: RewriteRule ^no/torrent(.*)$ /index.php/torrent/doit/$1 CodeIgniter会自动识别到 no 控 ...

  9. 在 SharePoint 2013 中选择正确的 API 集

    决定使用哪个 API 集的因素   您可以在多个 API 集中选择一个来访问 SharePoint 2013 平台.您使用哪一个 API 集取决于以下因素: 应用程序的类型. 可能的类型包括但不限于以 ...

  10. flume 集群安装

    ./pssh -h ./host/all.txt -P mkdir /usr/local/app ./pssh -h ./host/all.txt -P tar zxf /usr/local/soft ...