PHP实现cookie跨域session共享的方法分析


Posted in PHP onAugust 23, 2019

本文实例讲述了PHP实现cookie跨域session共享的方法。分享给大家供大家参考,具体如下:

做过web开发的小伙伴们都了解cookie和session,cookie是存储在客户端的,session是存储在服务器的。

本篇主要通过一些实践中的案例和大家分享一下踩到坑,重点说明了cookie跨域问题和session服务器共享问题,以php语言为使用语言进行说明。

先聊聊cookie

设置cookie无效

setcookie("sso", "e589hR6VnO8K1CNQZ4PSP/LWGBhRKE5VckawQwl1TdE8d4Q5E7tW", 900);

这个问题很多刚入门php的小伙们都会碰到。这个代码的本意应当是想设置cookie sso的有效期为15分钟,可是执行这个代码后发现没有效果。为什么呢?因为第三个参数expire表示的是过期的时间节点,而不是有效时间,所以如果希望设置cookie为15分钟,正确的做法应当是获取当前的时间戳加上15分钟。

setcookie这个函数还有path、domain参数都比较常用,强烈建议刚学php的小伙们多翻阅手册。php手册地址: http://php.net/manual/zh/index.php

获取cookie值获取不到

先看这样一段代码

setcookie("sso", "e589hR6VnO8K1CNQZ4PSP/LWGBhRKE5VckawQwl1TdE8d4Q5E7tW", time() + 900);
var_dump($_COOKIE["sso"]);

要解决这个问题,要先了解一下setcookie后发生了什么?因为cookie是保存在客户端的,php是服务端语言,实际上setcookie之后只是在返回的http头增加一个cookie的头信息,告诉客户端需要设置一个酱紫的cookie,如下图:

PHP实现cookie跨域session共享的方法分析

php中setcookie返回的http头

而$_COOKIE这个数组里面保存客户端传递上来的cookie。自然第一次刷新的时候因为客户端没有相应的cookie值,所以$_COOKIE是没有sso的信息的。第一次请求过后,因为服务器设置了cookie sso,所以第一次请求过来客户端就有了cookie sso的信息,所以第二次请求的时候就会带上sso的信息,服务端就能通过$_COOKIE取到值了。

cookie跨域问题

这个可以说是cookie中一个比较热门的问题,面试的时候一般很爱聊这方面的问题。

跨域的业务需求大概是酱紫:用户在a.com进行了登录,希望在b.com也同步进行了登录。如果是同一个主域比较简单,可以通过setcookie中的domain参数进行设定:例如有x.a.com和xx.a.com,可以通过设置domain为a.com,从而a.com的所有二级域名都可以共享这一个cookie。基于安全方面的原因,在a.com下面设置domain为b.com是无效的。

那么是否真的没有办法可以实现这个了呢?这个还是有一些奇巧淫技的,这里介绍一种使用内框iframe的方法。

具体思路:在a.com下设置cookie后,嵌入一个iframe框链接b.com的页面,b.com设置好页面cookie后,再嵌入一个a.com的页面,然后通过parent.parent就可以调用最外层的a.com的js方法,从而进行跳转或者一些其它的操作。具体代码示例如下:

假设a.com有页面:login.php和callback.php,b.com有页面synclogin.php

a.com的login.php代码:

<?php
$sso = "e589hR6VnO8K1CNQZ4PSP/LWGBhRKE5VckawQwl1TdE8d4Q5E7tW";
setcookie("sso", $sso);
?>
login success...
<script type="text/javascript">
  function jumpTo() {
    location.href = "http://a.com";
  }
</script>
<iframe src="http://b.com/synclogin.php?sso=<?php echo $sso; ?>"></iframe>

b.com的synclogin.php页面

<?php
setcookie("sso", $_GET["sso"]);
?>
<iframe src="http://a.com/callback.php"></iframe>

a.com的callback.php页面

<script type="text/javascript">
  parent.parent.jumpTo();
</script>

代码看起来也不难,值得一提的是这里嵌入了两个iframe,因为如果只用一个iframe的话,即在b.com的synclogin.php内直接调用父窗体的jumpTo方法,在有些浏览器下会提示没有权限的错误:
Error: Permission denied to access property

这里只是演示了cookie跨域同步的思路,具体细节还有很多可以改进的地方,比如iframe链接的页面可以考虑改成静态的页面,这样效率会比php动态页面快很多,还有像参数校验、多个主域(比如还有c.om)同时登录等等,这里就不再累述。

cookie的总结到这里就结束,如果你感觉有一些收获,可以在页面底部扫码给我打赏哟,感谢O(∩_∩)O~

session

$_SESSION没有值

这个session使用和cookie有一点不太一样,session使用前必须先调用session_start方法。否则会收到一个undefined的错误:
Notice: Undefined variable: _SESSION

session存储在哪

session存储在服务端,但是session究竟是存储在哪呢?php.ini中关于session有一个save_path的选项可以设置存放的目录,如果这个选项没有设置值,那么就存储在系统默认的tmp目录下。默认的tmp目录可以通过sys_get_temp_dir方法取到。

例如在mac下面,php的session一般会存储在/var/tmp目录下。

session_start();
echo session_id();//本例输出ipkl446enhae25uq92c28u4lo3
$_SESSION['name'] = "tony”;
$_SESSION['users'] = array("tony", "andy");

通过session_id方法可以取到当前的session编号,通过这个编号可查看一下该session文件。

$ sudo more /var/tmp/sess_ipkl446enhae25uq92c28u4lo3
name|s:4:"tony";users|a:2:{i:0;s:4:"tony";i:1;s:4:"andy";}

可以清楚的看到session存储数据的结构,其中值是用序列化的方式进行转化存储的。

session也用了cookie

session不是存储在服务端吗,怎么又和cookie扯上关系了?其实想想也简单,因为客户端再请求的时候,服务端怎么样才能知道该客户端的session存储在哪个文件呢?其实也是通过cookie PHPSESSID来进行标识。

PHP实现cookie跨域session共享的方法分析

php中session的cookie标识

php在进行session操作的时候会生成一个session id,而后把这个值以cookie的形式保存在客户端,就是图示中的PHPSESSID了。客户端在下次请求的时候就会带上这个PHPSESSID,服务端就能知道当前客户端对应的session文件了

session超时设置

cookie超时设置比较简单,一个参数就搞定了。session这边有点小麻烦,既不能单独设置cookie PHPSESSID的超时时间,也不能单独设置服务端文件的超时时间。具体的可以参考鸟哥这篇文章:如何设置一个严格30分钟过期的Session,真的非常严谨,赞一下。

session服务器共享

这个问题和cookie的跨域类似,面试的时候也很爱聊这个问题。

以前在做服务器集群的时候会碰到这样的一样问题,就是用户一会访问是处于正常登录状态,一会访问又没有登录了。这个问题偶尔才会出现。跟踪代码下去才发现session没有取到相应的值,想想也是醉了:原来服务器session没有设置共享,session存在在本地文件目录,当用户访问另外一台服务器的时候自然就取不到session了。

解决方法也不难,通过共享的存储在进行服务器之间的共享。这里使用redis的进行session存储。可以通过php.ini配置文件进行调整,也可以在代码中通过ini_set进行调整

ini_set("session.save_handler", "redis");
ini_set("session.save_path", "tcp://127.0.0.1:6379”);

如果需要使用redis进行存储,需要session中的Registered save handlers支持redis

PHP实现cookie跨域session共享的方法分析

php中session是否支持redis

当这样设置之后,session就会保存在redis中了,不同的集群服务器之间就可以通过该redis服务器进行共享了。

好吧,暂时就写到这里了,以后会发现新的坑会继续补充上来。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP学习资料汇总与网址
Mar 16 PHP
发款php蜘蛛统计插件只要有mysql就可用
Oct 12 PHP
PHP开发中四种查询返回结果分析
Jan 02 PHP
php图片加中文水印实现代码分享
Oct 31 PHP
PHP导航下拉菜单的实现如此简单
Sep 22 PHP
PHP在引号前面添加反斜杠(PHP去除反斜杠)
Sep 28 PHP
PHP小教程之实现双向链表
Jun 12 PHP
Yii框架调试心得--在页面输出执行sql语句
Dec 25 PHP
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
May 21 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
yii2.0实现pathinfo的形式访问的配置方法
Apr 06 PHP
浅谈PHP命令执行php文件需要注意的问题
Dec 16 PHP
php常用经典函数集锦【数组、字符串、栈、队列、排序等】
Aug 23 #PHP
php中错误处理操作实例分析
Aug 23 #PHP
php+js实现的无刷新下载文件功能示例
Aug 23 #PHP
php简单检测404页面的方法示例
Aug 23 #PHP
PHP Redis扩展无法加载的问题解决方法
Aug 22 #PHP
PHP Primary script unknown 解决方法总结
Aug 22 #PHP
php用wangeditor3实现图片上传功能
Aug 22 #PHP
You might like
Knockoutjs的环境搭建教程
2012/11/26 Javascript
js调用webservice中的方法实现思路及代码
2013/02/25 Javascript
jquery实现在光标位置插入内容的方法
2015/02/05 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
js实现下一页页码效果
2017/03/07 Javascript
深入理解ES7的async/await的用法
2017/09/09 Javascript
微信小程序如何像vue一样在动态绑定类名
2018/04/17 Javascript
js计时事件实现圆形时钟
2020/03/25 Javascript
javascript代码实现简易计算器
2021/01/25 Javascript
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python 中文字符串的处理实现代码
2009/10/25 Python
MySQL最常见的操作语句小结
2015/05/07 Python
Python实现的文本编辑器功能示例
2017/06/30 Python
Python实现的端口扫描功能示例
2018/04/08 Python
python实现简单登陆流程的方法
2018/04/22 Python
python3 拼接字符串的7种方法
2018/09/12 Python
Python调用adb命令实现对多台设备同时进行reboot的方法
2018/10/15 Python
Django实现单用户登录的方法示例
2019/03/28 Python
Python简易计算器制作方法代码详解
2019/10/31 Python
如何使用Django Admin管理后台导入CSV
2020/11/06 Python
python 爬取小说并下载的示例
2020/12/07 Python
详解css3 flex弹性盒自动铺满写法
2020/09/17 HTML / CSS
摩飞电器俄罗斯官方网站:Morphy Richards俄罗斯
2020/07/30 全球购物
自动化专业本科毕业生求职信
2013/10/20 职场文书
家电业务员岗位职责
2014/03/10 职场文书
关于环保的建议书400字
2014/03/12 职场文书
公司年终奖分配方案
2014/06/16 职场文书
个人授权委托书模板
2014/09/14 职场文书
客户付款通知书
2015/04/23 职场文书
学雷锋团日活动总结
2015/05/06 职场文书
初中教师德育工作总结2015
2015/05/12 职场文书
入党群众意见范文
2015/06/02 职场文书
亮剑观后感500字
2015/06/05 职场文书
php 文件上传至OSS及删除远程阿里云OSS文件
2021/07/04 PHP
Android自定义ScrollView实现阻尼回弹
2022/04/01 Java/Android
Win10服务全部禁用了怎么启动?Win10服务全部禁用解决方法
2022/09/23 数码科技