文档章节

基于thinkphp的ajax跨域解决方案

l
 lighthouse
发布于 2015/06/29 09:49
字数 979
阅读 302
收藏 0

周末在家仔细研究了一下ajax跨域的问题,虽然可以用jsonp但jsonp只能用于GET请求,所以还是深入了一下。

CORS的具体内容大家可网上搜一下,这里主要是设置一个名为“Access-Control-Expose-Headers”的报头对响应报头进行授权。PHP中使用header("Access-Control-Allow-Origin:*");就可以了。

thinkphp中 控制器返回之前加一行header("Access-Control-Allow-Origin:*");也能成功,但是如果每个控制器函数都写这么一句就太费事了。所以创建了一个AjaxController类继承Controller类,并在构造函数中添加了

class AjaxController extends Controller {

   public function __construct(){
       parent::__construct();//调用父类的方法,因为这里重写了父类的方法
       //用于解决前台ajax跨域请求
     header("Access-Control-Allow-Origin:*");
       //header("Access-Control-Allow-Origin:http://111.com");
   }
}

其他控制器全部继承此类

class IndexController extends AjaxController {

 测试成功。但又发现另一个问题

thinkphp文档里提到的success和error方法会自动判断当前请求是否属于Ajax请求,如果属于Ajax请求则会调用ajaxReturn方法返回信息。 ajax方式下面,success和error方法会封装下面的数据返回:

经过一翻排查发现success并没有以ajax方式返回。这里有两个解决方法,一是指定success的第三个参数为true(error同理)。

但这样就失去了灵活性,本着一挖到底的原则最后找到了\ThinkPHP\Library\Think\Controller.class.php中的

private function dispatchJump($message,$status=1,$jumpUrl='',$ajax=false) {
   if(true === $ajax || IS_AJAX )

 这里用于判断是否为ajax提交过来的。IS_AJAX在\ThinkPHP\Library\Think\App.class.php中,内容为

define('IS_AJAX',       ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')])) ? true : false);

看来IS_AJAX并不能很好的反映是否为ajax提交。所以在App.class.php又增加了IS_AJAX2的定义

switch ($_SERVER['HTTP_ACCEPT']){//定义常量IS_AJAX2 用于判断ajax跨域提交
   case 'application/json, text/javascript, */*':
       //  JSON 格式
       define('IS_AJAX2',true);
       break;
   case 'text/javascript, application/javascript, */*':
       // javascript JSONP 格式
       define('IS_AJAX2',true);
       break;
   case 'text/html, */*':
       //  HTML 格式
       break;
   case 'application/xml, text/xml, */*':
       //  XML 格式
       break;
}

并修改Controller.class.php中dispatchJump函数

private function dispatchJump($message,$status=1,$jumpUrl='',$ajax=false) {
   if(true === $ajax || IS_AJAX ||IS_AJAX2) {//IS_AJAX2 用于判断ajax跨域提交

这样问题就彻底解决了,但因为改动了框架函数,对于以后升级带了不便,不知道有没有其他更好的方案。

还有另一个需要修改的地方就是Controller.class.php中的ajaxReturn函数也要增加header("Access-Control-Allow-Origin:*"),不然的使用$this->ajaxreturn也不支持跨域

protected function ajaxReturn($data,$type='',$json_option=0) {
   
if(empty($type)) $type  =   C('DEFAULT_AJAX_RETURN');
   
switch (strtoupper($type)){
       
case 'JSON' :
           
// 返回JSON数据格式到客户端 包含状态信息
           
header('Content-Type:application/json; charset=utf-8');
           
header("Access-Control-Allow-Origin:*");//用于解决前台ajax跨域请求 libo
           exit(json_encode($data,$json_option));
       
case 'XML'  :
           
// 返回xml格式数据
           
header('Content-Type:text/xml; charset=utf-8');
           
exit(xml_encode($data));
       
case 'JSONP':
           
// 返回JSON数据格式到客户端 包含状态信息
           
header('Content-Type:application/json; charset=utf-8');
           
header("Access-Control-Allow-Origin:*");//用于解决前台ajax跨域请求 libo
           $handler  =   isset($_GET[C('VAR_JSONP_HANDLER')]) ? $_GET[C('VAR_JSONP_HANDLER')] : C('DEFAULT_JSONP_HANDLER');
           
exit($handler.'('.json_encode($data,$json_option).');');  
       
case 'EVAL' :

 再说一下前台的$.ajax需要注意的就是 在IE10中textStatus一直为parsererror,导致结果一直为error,测试发现是浏览器安全设置问题。然后在jquery官方找到了$.ajax的crossDomain: true,这个参数,但还是没效果。最后用了jQuery.support.cors = true;

        jQuery.support.cors = true;//提供了这样的方式来支持浏览器的跨站请求 IE10有效
        $.ajax({
            url: "http://xxxx/Home/index/ajaxlogin",
            data: {"uid":$name,"upw":$pw},
            timeout: 5000,
            cache: false,
            type: "POST",
            dataType: "json",//如果返回类型与dataType不同,会使textStatus为parsererror而导致执行error函数
            crossDomain: true,//Jquery1.5之后,提供了这样的方式来支持浏览器的跨站请求。(经测试IE10及以下无效,但在ajax请求前设置jQuery.support.cors = true;有效)

© 著作权归作者所有

l
粉丝 0
博文 5
码字总数 4651
作品 0
威海
私信 提问
加载中

评论(1)

rocky
rocky
79帅.
ThinkPHP 5.1.37 开发跨域问题解决

1.查阅 ThinkPHP 的文档,文档给出的例子: 只需要在路由的尾部添加 allowCrossDomain() 即可实现跨域请求,所以我在每个需要进行跨域访问的路由后都添加了 ->allowCrossDomain(),一般的跨域...

后盾风云
07/08
116
0
thinkphp开发的框架的简单介绍

  说起来现在的互联网时代中用到thinkphp的地方也是很多的,这也是一项技术活,开发框架也是比较有难度的,下面就给大家简单地介绍一下。   ThinkPHP是一个免费开源的,快速、简单的面向...

孙智绘
2012/06/28
54
0
PHP学习路线图 最全PHP自学指南

对于广大零基础的PHP自学者,往往不知道如何系统的学习PHP,导致平白浪费了很多时间。本文将为大家带来最详细的php学习路线图,同时还会附上相应的权威教程,让广大PHP自学者少走许多弯路。 ...

W3Cschool小编
2018/04/24
0
0
OSChina 第 11 期高手问答,主题:ThinkPHP

ThinkPHP 是一个开源的、快速、简单的面向对象的轻量级PHP开发框架,遵循Apache开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计...

红薯
2012/03/10
8.4K
50
Workerman集成ThinkPHP

关于Workerman与ThinkPHP集成的问题,相信已经有大神给出了答案。不过因为各人理解不一样,解决方案也是互有异同。 ThinkPHP版本:3.2.1+ Workerman版本:3.3.0+ 第一步:将Workerman复制到T...

零度开水
2016/05/27
6.5K
4

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周二乱弹 —— 他只能用这个办法劝你注意身体了

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @-冰冰棒- :#今日歌曲推荐# Kodaline《High Hopes》 《High Hopes》- Kodaline 手机党少年们想听歌,请使劲儿戳(这里) @xiaoshiyue :仙女...

小小编辑
15分钟前
479
12
Spring Boot Actuator 整合 Prometheus

简介 Spring Boot 自带监控功能 Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、环境变量、日志信息、线程信息等。这一节结合 Prometheus 、Grafana 来更加直观...

程序员果果
24分钟前
6
0
Linux文件查找命令详解

对于文件查找,我们最好用的还是属于find命令了,在说find命令之前,先把另外几个查找命令介绍一下。 目录 0x01 查询命令介绍 0x02 find命令介绍 0x01 查询命令介绍 在介绍之前,首先先了解一...

无心的梦呓
24分钟前
4
0
快速掌握的测试用例优先级划分方法

怎么样的设计才能算测试用例 引自:IEEE Standard 610 (1990): A set of test inputs, execution conditions, and expected results developed for a particular objective, such as to exe......

测者陈磊
28分钟前
3
0
[mycat]Attribute value "roadNodeId,version" of type NMTOKEN must be a name token

不能逗号配两个字段的主键 primaryKey="roadNodeId,version" Caused by: io.mycat.config.util.ConfigException: org.xml.sax.SAXParseException; lineNumber: 7; columnNumber: 105; Attrib......

Danni3
33分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部