ThinkPHP 后台 Ajax 如何跨域

1,935 阅读3分钟
原文链接: www.jianshu.com

  • 由于后台或前端的不同,配置都可能不同;搞了一上午,对于我这个前端新生儿很苦恼,故分享给大家,先说下我的场景:
    --- 后台 ---
    ThinkPHP 版本3.2.3
    XAMPP 部署
    --- 前端 ---
    JQuery 版本1.11.3
    Chrome浏览器

  • 如果你不是我的场景,或者有其他问题,即使没有问题我也建议你看一下这两个博客
    www.jianshu.com/p/82b82d5dd…
    app.epoint.com.cn/doc.web.cro…

什么是跨域?

如果你使过苹果手机,你一定听说过越狱。而跨域就是为了突破 web安全的基石“同源策略”的限制,由网景公司在1995年提出,目前所有浏览器都在实行。

  • 同源指的是
    1.协议相同 2.域名相同 3.端口相同

  • 以下限制
    1.Cookie、LocalStorage 和 IndexDB 无法读取
    2.DOM 无法获得
    3.AJAX 请求不能发送

  • 举个例子
    http//www.demo.com:80/index.html
    http 就是协议, www.demo.com 就是域名, 80就是端口
    如果没有同源网站A拿到了网站B的隐私Cookies,这里面可能包含登陆信息,用户权限。造成一些安全问题,等....

如何跨域?

  • 这里只说Ajax如何去跨域,如果你想知道如何共享Cookie等,请参考上面我推荐的文章。先说一下我要演示接口的作用,就是添加一个用户。

在浏览器上GET请求测试成功,串为http://127.0.0.1/GitHubStart/index.php/Home/Index/android?param={"data":{"user":"akkk1e9962","password":"1231231231","zone":"1"}}&method=entry
返回值为{"status":"false","msg":"\u5e10\u53f7\u5df2\u5b58\u5728"}
So. 接口是没问题的,继续

  • 首先在PHP中,任何一个返回的Controller中加上
    header('Access-Control-Allow-Origin:*');   // 指定允许其他域名访问 
    header('Access-Control-Allow-Headers:x-requested-with,content-type');// 响应头设置

我是在入口控制器就添加了,这样就不必要去为后面的页面再添加了

<?php
namespace Home\Controller;
use Think\Controller;
import('Home.View.Api');

header('content-type:application:json;charset=utf8');  
header('Access-Control-Allow-Origin:*');   // 指定允许其他域名访问 
header('Access-Control-Allow-Headers:x-requested-with,content-type');// 响应头设置  

class IndexController extends Controller {
   /**
     * iOS访问后台程序的入口
     */
    public function ios(){
        $method=$_POST['method']==null?$_GET['method']:$_POST['method'];
        $param=$_POST['param']==null?$_GET['param']:$_POST['param'];
        call_user_func_array(array('Api',$method),$param); 
    }
    /**
     * Android/Web访问后台程序的入口
     */
    public function android(){
        $method=$_POST['method']==null?$_GET['method']:$_POST['method'];
        $param=$_POST['param']==null?$_GET['param']:$_POST['param'];
        $param=json_decode($param,true);
        call_user_func_array(array('Api',$method),$param); 
    }
}
  • 在前端JS中,去请求数据
    按照前面的GET串,我们拼接一下Ajax的data
    data:{
              param:{
                  data: {
                      user:"akkk1e9962",
                      password:"1231231231",
                      zone:"1"
                  }
              },
              method:"entry"
          },
    对照一下
    param={"data":{"user":"akkk1e9962","password":"1231231231","zone":"1"}}&method=entry
    ok . 木有毛病

快乐的点击保存,然而并没有什么卵用,What the.... FFFFFFF ,审查下元素



200 OK ...... 差点就被迷糊了.. 去JS一看,请求失败


审查一下,也没有提示警告了,证明已经跨域成功了



这样的话,参数是不是传的不正确呢?



  • 结论,我所需要的param字典参数,需要当成字符串来处理,而不是对象。
var dict =  {
        data: {
            user:user,
            password:password,
            zone:zone
        }
    };

    $.ajax({
        url: IP,
        type: 'get',
        dataType:'json',
        async:true,
        data:{
            param: JSON.stringify(dict),
            method:method
        },
        success: function(res) {
            if(res["success"]){
                alert(res["msg"]);
            }
            else {
                alert(res["msg"]);
            }
        },
        error:function(res){
            alert("请求失败");
        }
    });

Done ..