php中cookie跨域的解决方案以及IE和safari浏览器中的坑
2015-10-13 23:23
671 查看
最近工作上遇到了一道难题:公司的合作商想将我们平台的用户引流到他们平台,即在他们的网站上用户可以使用在我们平台的用户名和密码进行登录,简言之需要做到用户在两个平台登录状态的同步。
一般来说用户登录完之后用户信息存储在cookie中,要实现登录状态的同步实际上就是要实现cookie的跨域共享。
具体的实现思路是,a网站不存储cookie,b网站提供cookie的获取接口,a网站实时请求该接口,获取用户信息。简要的示例如下:
cookie接口:passport.b.com/cookie.php
a网站公用部分代码:
在请求http://passport.b.com/cookie.php链接时,输出的数据将调用在js中定义的outputCookie方法,在该方法中处理有用户有关的逻辑。
原理与ajax的jsonp跨域请求的原理十分类似,不明白jsonp的机制的童鞋建议移步这篇文章:浅谈jsopn跨域请求原理及cors(跨域资源共享)解决方案。
看起来很浅显而且容易,但是当真正实现起来时却遇到了IE和safari两只拦路虎。先上代码:
www.a.com/index.php(a站首页代码)
passport.b.com/login.php(b站登录接口)
以上的代码在firefox和chome中运行良好,在IE和safari中却出了问题:
IE的问题:
在IE中测试时发现login.php接口始终中不上cookie。
解决方案:
其实很简单,在种cookie前用php设置一下p3p头即可,在login.php的setcookie方法前加上如下代码:
safari的问题:
在safari中有IE一样的问题,处理起来比IE要稍微复杂一点,必须使用302跳转来种cookie
解决方案:
不使用script的src标签请求cookie接口,直接使用location.href跳转到指定接口再跳转回该页面,整个过程在较短的时间内就能完成,不会对用户体验造成太大影响。
具体实现代码:
www.a.com/index.php部分代码:
passport.b.com/loginForSafari.php(b站为Safari设置的登录接口):
关于php中cookie跨域的解决方案以及IE和safari浏览器中的坑就介绍到这里,希望对各位有所帮助。
一般来说用户登录完之后用户信息存储在cookie中,要实现登录状态的同步实际上就是要实现cookie的跨域共享。
具体的实现思路是,a网站不存储cookie,b网站提供cookie的获取接口,a网站实时请求该接口,获取用户信息。简要的示例如下:
cookie接口:passport.b.com/cookie.php
<?php echo 'outputCookie'.'('.json_encode($_COOKIE).')';
a网站公用部分代码:
<div id="userinfo"> <div id="noLogin" style="display:none"> 用户名:<input name="username" type="text" id="username" /><br /> 密码:<input name="password" type="text" id="password" /><br /> <input type="submit" id="submit" value="登录"/> <span id="tips"><?php echo isset($_GET['msg']) ? urldecode($_GET['msg']) : '' ?></span> </div> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <script> function outputCookie(data){ if(data && data.username){ $("#userinfo").html('你好,' + data.username + '<a href="http://passport.b.com/logout.php">登出</a>'); }else{ // document.getElementById('noLogin').style.display="block"; $("#noLogin").show(); } }; </script> <script src="http://passport.b.com/cookie.php"></script>
在请求http://passport.b.com/cookie.php链接时,输出的数据将调用在js中定义的outputCookie方法,在该方法中处理有用户有关的逻辑。
原理与ajax的jsonp跨域请求的原理十分类似,不明白jsonp的机制的童鞋建议移步这篇文章:浅谈jsopn跨域请求原理及cors(跨域资源共享)解决方案。
看起来很浅显而且容易,但是当真正实现起来时却遇到了IE和safari两只拦路虎。先上代码:
www.a.com/index.php(a站首页代码)
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <div id="userinfo"> <div id="noLogin" style="display:none"> 用户名:<input name="username" type="text" id="username" /><br /> 密码:<input name="password" type="text" id="password" /><br /> <input type="submit" id="submit" value="登录"/> <span id="tips"><?php echo isset($_GET['msg']) ? urldecode($_GET['msg']) : '' ?></span> </div> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <script> function outputCookie(data){ if(data && data.username){ $("#userinfo").html('你好,' + data.username + '<a href="http://passport.b.com/logout.php">登出</a>'); }else{ // document.getElementById('noLogin').style.display="block"; $("#noLogin").show(); } }; function doSomething(data){ if(data.status != 1){ $("#tips").html(data.msg); }else{ window.location.reload(); } } </script> <script> $(function(){ $("#submit").click(function() { var username = $("#username").val(); var password = $("#password").val(); if(!username || !password){ $("#tips").html('用户名和密码不能为空!'); }else{ //在safari之外的浏览器是可以这样实现的 var script = document.createElement( 'script' ); script.type = 'text/javascript'; script.src = 'http://passport.b.com/login.php?username=' + username + '&password=' + password + '&callback=doSomething'; $("body").append( script ); } }); }); </script> <script src="http://passport.b.com/cookie.php"></script>
passport.b.com/login.php(b站登录接口)
<?php if(empty($_GET['username']) || empty($_GET['password']) || empty($_GET['callback'])){ echo $_GET['callback'].'('.json_encode(array('status' => -1,'msg' => '参数不完整')).')'; } if($_GET['username'] == 'ben' && $_GET['password'] == 'lalala'){ //设置cookie setcookie('username', 'ben', time() + 60*60*24*365, '/'); echo $_GET['callback'].'('.json_encode(array('status' => 1,'msg' => 'ok')).')'; }else{ echo $_GET['callback'].'('.json_encode(array('status' => -2,'msg' => '用户名或密码错误')).')'; }http://passport.b.com/logout.php(b站登出接口)
<?php setcookie('username', 'ben', time() - 60, '/'); header("Cache-control:no-cache,no-store,must-revalidate"); header("Pragma:no-cache"); header("Expires:0"); header("Location:http://www.a.com");
以上的代码在firefox和chome中运行良好,在IE和safari中却出了问题:
IE的问题:
在IE中测试时发现login.php接口始终中不上cookie。
解决方案:
其实很简单,在种cookie前用php设置一下p3p头即可,在login.php的setcookie方法前加上如下代码:
<span style="font-size:10px;">header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');</span>
safari的问题:
在safari中有IE一样的问题,处理起来比IE要稍微复杂一点,必须使用302跳转来种cookie
解决方案:
不使用script的src标签请求cookie接口,直接使用location.href跳转到指定接口再跳转回该页面,整个过程在较短的时间内就能完成,不会对用户体验造成太大影响。
具体实现代码:
www.a.com/index.php部分代码:
<script> $(function(){ $("#submit").click(function() { var username = $("#username").val(); var password = $("#password").val(); if(!username || !password){ $("#tips").html('用户名和密码不能为空!'); }else{ <span style="color:#00cccc;">var explorer =navigator.userAgent; if(explorer.indexOf("Safari") >= 0){ //safari下需要做跳转 location.href='http://passport.b.com/loginForSafari.php?username=' + username + '&password=' + password;</span> }else{ //在safari之外的浏览器是可以这样实现的 var script = document.createElement( 'script' ); script.type = 'text/javascript'; script.src = 'http://passport.b.com/login.php?username=' + username + '&password=' + password + '&callback=doSomething'; $("body").append( script ); } } }); }); </script>
passport.b.com/loginForSafari.php(b站为Safari设置的登录接口):
<?php if(!empty($_GET['username']) && !empty($_GET['password'])){ if($_GET['username'] == 'ben' && $_GET['password'] == 'lalala'){ setcookie('username', 'ben', time() + 60*60*24*365, '/'); header("Location:http://www.a.com"); exit(); } } header("Location:http://www.a.com?msg=".urlencode('用户名或密码错误!')); exit();
关于php中cookie跨域的解决方案以及IE和safari浏览器中的坑就介绍到这里,希望对各位有所帮助。
相关文章推荐
- 一个关于if else容易迷惑的问题
- PHP5.2.*防止Hash冲突拒绝服务攻击的Patch
- 深入理解PHP之匿名函数
- 广告行业抱怨 Safari 的防追踪技术 ITP 太有效,严重影响收入
- JSP/PHP基于Ajax的分页功能实现
- 关于PHP通过PDO用中文条件查询MySQL的问题。
- 什么是设计模式
- PHP数据库长连接mysql_pconnect的细节
- Php Installing An Expansion
- IE右键菜单被修改
- IE:获取完整的网页
- IE:脱机浏览网页
- 利用IE收听“广播”
- 清除IE分级审查密码
- IE:添加编辑器
- IE:“自动完成”功能
- IE:如何做到全屏显示
- 给IE加个参数 永远不怕IE主页被修改
- IE:使用搜索助手