thinkphp中session跨域问题
问题描述
《thinkphp实现短信验证注册》中,小编不止记录了短信验证码的实现方法,同时还记录了图片验证码的实现方法。
本地使用,一切正常;后端项目和前端项目都部署到服务器,一切正常;后端项目部署到服务器,并设置允许跨域访问后,本地前端项目使用服务器上后端项目接口时,问题来了:
首先,使用postman测试获取图片验证码接口和验证图片验证码接口,正常。
然后,在html中使用获取图片验证码接口,正常;最后,在JS中使用验证图片验证码接口,出错!!!
分析
通过问题描述,我们看出,问题出现在跨域上。那么,有两种可能,一种是因为跨域设置不正确;一种是因为thinkphp本身的问题。
采用另外一种跨域配置,问题依然存在。那就是thinkphp本身的问题了,经查找资料,问题定位在thinkphp的session跨域上。
跨子域解决办法
其实不管是ThinkPHP还是php本身,在解决session跨域问题的时候都需要设置session.cookie_domain。
针对session跨域这一问题的解决方法主要有以下几种:
第一种情况:如果目录下没有.htaccess这个文件,也就是没有采取url伪静态的话,那么,在conf/config.php的第一行加上:
ini_set('session.cookie_domain',".domain.com");//跨域访问Session
这时如果你开启了调试,那么可以用!但关闭了调试,就不管用了!
第二种情况:如果你目录下有.htaccess这个文件,那么你在根目录,index.php的第一行加入:
<?php ini_set('session.cookie_domain',".domain.com");//跨域访问Session
// 应用入口文件
?>
这种方法不管开不开启调试都管用!
然而,我们的问题并不是跨子域的问题,而是完全跨域,所以上述方法无效。
完全跨域解决办法
获取图片验证码请求
查看获取图片验证码的请求信息,Request Headers为:
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Cookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3D
Host:api.voidking.com
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Response Headers为:
Access-Control-Allow-Origin:*
Cache-Control:post-check=0, pre-check=0
Cache-Control:private, max-age=0, no-store, no-cache, must-revalidate
Connection:keep-alive
Content-Type:image/png
Date:Sun, 27 Nov 2016 12:10:44 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Set-Cookie:PHPSESSID=721t4sqanvsii550m1dk8gq1o3; path=/; domain=.voidking.com
Transfer-Encoding:chunked
验证验证码请求
查看验证验证码的请求信息,Request Headers为:
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:9
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:api.voidking.com
Origin:http://localhost
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Response Headers为:
Access-Control-Allow-Origin:*
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Sun, 27 Nov 2016 12:13:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Set-Cookie:PHPSESSID=149t0hhs2icqaaemvp39onkgp4; path=/; domain=.voidking.com
Transfer-Encoding:chunked
Vary:Accept-Encoding
再次获取图片验证码请求
Request Headers为:
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3D; PHPSESSID=721t4sqanvsii550m1dk8gq1o3
Host:api.voidking.com
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Response Headers为:
Access-Control-Allow-Origin:*
Cache-Control:private, max-age=0, no-store, no-cache, must-revalidate
Cache-Control:post-check=0, pre-check=0
Connection:keep-alive
Content-Type:image/png
Date:Sun, 27 Nov 2016 13:26:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Transfer-Encoding:chunked
三次请求比较
第一次获取图片验证码请求,Cookie中没有PHPSESSID,所以,返回信息中有Set-Cookie。第二次获取图片验证码请求,Cookie中含有PHPSESSID,所以,返回信息中没有了Set-Cookie。而且第一次请求返回信息Set-Cookie中的PHPSESSID,和第二次请求请求信息Cookie中的PHPSESSID是相同的。
而验证图片验证码的ajax请求,没有Cookie,自然也没有PHPSESSID,所以,返回信息中也有Set-Cookie。
可见,我们需要在前端做一些修改,使之发送请求时带着Cookie。
前端jquery设置
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>jquery</title>
</head>
<body>
<p>
<img src="http://api.voidking.com/owner-bd/index.php/Home/CheckCode/getPicCode" alt="">
<input type="text" id="picCode">
<input type="button" id="send" value="验证">
</p>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
$(function(){
$('#send').click(function(){
//console.log(document.cookie);
$.ajax({
url: 'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode',
type: 'POST',
crossDomain: true,
xhrFields: {
withCredentials: true
},
dataType: 'json',
data: {code: $('#picCode').val()},
success: function(data){
console.log(data);
},
error: function(xhr){
console.log(xhr);
}
});
});
});
</script>
</body>
</html>
请求时报错如下:
A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
出现了跨域报错,可见后端也需要做一些修改,使之可以接收跨域Cookie。
后端nginx设置
add_header Access-Control-Allow-Origin http://localhost;
add_header Access-Control-Allow-Credentials true;
注意:
服务器端Access-Control-Allow-Credentials参数为true时,Access-Control-Allow-Origin参数的值不能为*。
后端nginx设置后,jquery的ajax请求正常了,可以携带Cookie,后端正常接收数据并返回数据。
由于angular的ajax请求不同于jquery,所以,我们还需要研究一下angular怎么发送携带Cookie的跨域请求。
前端angular设置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>angular</title>
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body ng-app="myApp" >
<p ng-controller="myCtrl">
<img src="http://api.voidking.com/owner-bd/index.php/Home/CheckCode/getPicCode" alt="">
<input type="text" id="picCode" ng-model="picCode">
<input type="button" ng-click="send()" value="验证">
</p>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $httpParamSerializer) {
$scope.send = function(){
$http({
method:'POST',
url:'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
},
withCredentials: true,
dataType: 'json',
data: $httpParamSerializer({code: $scope.picCode})
}).then(function successCallback(response) {
console.log(response.data);
$scope.username = response.data.username;
}, function errorCallback(response) {
console.log(response.data);
});
}
});
</script>
</body>
</html>
后记
至此,大功告成,session跨域问题完美解决。
书签
ThinkPHP框架实现session跨域问题的解决方法
http://www.jb51.net/article/51722.htm
ThinkPHP二级域名session共享问题
http://www.thinkphp.cn/topic/6380.html
php 跨域、跨子域,跨服务器读取session
http://blog.csdn.net/kylinbl/article/details/7634075
跨服务器Session共享的四种方法
http://blog.sina.com.cn/s/blog_5f3d71430100jv7q.html
Angular通过CORS实现跨域方案
https://my.oschina.net/blogshi/blog/303758
thinkphp中session跨域问题的更多相关文章
- thinkphp session 跨域问题解决方案
session 跨域,困扰我好几天,今天终于弄明白了! 不管是thinkphp ,还是本身的php 其实都要设置session.cookie_domain 设置好,就OK了 在thinkphp 里,在 ...
- php SESSION跨域问题
这段时间随着项目功能的扩展,慢慢接触到了跨域方面的知识,遇到的更多的问题也是前端与后端交互的时候跨域问题.关于js跨域的问题我会在其他分类里面写.这里记录我今天遇到的php session跨域问题 当 ...
- session跨域共享解决方案
要让session跨域共享,需要解决三个问题: 1.通过什么方法来传递session_id? 2.通过什么方法来保存session信息? 3.通过什么方法来进行跨域? 一.传递session_id有4 ...
- 谈谈我的session跨域处理方法
情景:公司的一个网站有一个模块(测试模块)需要单独用另外的一个域名(www.btest.com)去访问,即网站需要用两个不同的域名去访问,如首页(www.abc.com)和测试模块(www.xyz.c ...
- 【分布式系列】session跨域及单点登录解决方案
Cookie机制 Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息. ...
- 170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...
- sso单点登录的入门(Session跨域、Spring-Session共享)
1.单点登录,就是多系统,单一位置登录,实现多系统同时登录的一种技术.单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的. 区分与三方登录(第三方登录) ,三方登录:某系统,使用其他系统 ...
- java:sso(单点登录(single sign on),jsp文件动静态导入方式,session跨域)
1.jsp文件导入: 2.session跨域: 3.sso(单点登录(single sign on): sso Maven Webapp: LoginController.java: package ...
- session跨域共享问题解决方案
在讨论 session 跨域共享问题之前,我们首先要了解 session 做了什么,没做什么 1.HTTP是无状态的,也就是说服务器不知道谁访问过他,但是有时间,又需要我们去保留这个状态比如说用户的登 ...
随机推荐
- bootstrap table 服务器端分页例子分享
这篇文章主要介绍了bootstrap table 服务器端分页例子分享,需要的朋友可以参考下 1,前台引入所需的js 可以从官网上下载 复制代码代码如下: function getTab(){var ...
- SQL2005 安装时 “性能监视器计数器要求(错误)” 解决方案
转自SQL2005 安装时 "性能监视器计数器要求(错误)" 解决方案 出现此类问题一般都是在非法卸载sql2005出现的 在 "开始" --> &qu ...
- Python3整理文件
晚上打算把播放器下载下来的音乐拷贝到mp3里边,但是它是如下形式存放的,相当头痛…… 作为程序员,想到使用python来遍历这个目录,并将有大于限制的音乐文件拷贝到指定目录,相关实现代码如下: # a ...
- Linux本地无法登录,远程却可以登录
[root@oraserver ~]# vi /etc/pam.d/login 将以下内容注释掉: #session required /lib/security/pam_limits. ...
- Unreachable catch block for IOException. This exception is never thrown from the try statement body
Unreachable catch block for IOException. This exception is never thrown from the try statement body ...
- JavaScript字符串的操作
<script> var s=new String(); var s="Hello World"; alert(s.toLowerCase(s));//转小写 aler ...
- bzoj2209 2329
括号序列的经典做法把(看成1,)看成-1匹配的括号序列即任意前缀和都非负我们先解决静态的问题,给定一段括号序列求最少修改次数我们先找出最大后缀和a和最小前缀和b之间一定可以不相交显然a+|b|个括号是 ...
- 简单的单页c#生成静态页源码
protected void BtGroup_ServerClick(object sender, EventArgs e) { //产业群首页 ...
- Visual Studio 2015 企业版 官方中文版.iso
Visual Studio 2015 企业版 官方中文版.iso 附上链接 不要积分 谢谢: http://download.csdn.net/detail/onebelowzero2012/9561 ...
- 页面中引入带中文的JS文件乱码问题
1. WebConfig: <globalization requestEncoding="gb2312" responseEncoding="gb2312&quo ...