Ajax跨域请求的两种实现方式

最近网站新增了一个域名B用于分离不同的功能。但是需要复用服务器的高防等服务,但是服务和原有域名A绑定,所以新域名B需要直接去调用域名A。

一开始想使用CNAME的方式,让B直接指向A。但是Https支持性有点问题,需要多域名证书。也考虑过反向代理,但是代理服务器的性能和高防等又是一个问题。

最终决定在域名B的网页中,所有请求都直接去调用域名A的接口。于是就遇到了跨域请求的问题。

网上找了许多资料来实现跨域请求。最终预估下来,有两种方案比较靠谱:通过iframe实现和CORS方案

初步设想是加载一个域名A的iframe页面,然后通过postMessage将所有Ajax请求,转发给这个页面,通过这个页面来进行请求,最终将结果通过postMessage回发给外层的域名B页面。

于是开始实现:

前端使用的是React,所以实现了一个FrameHttp.js专门用法封装ajax调用。调用FrameHttp.ajax将所有外部Jquery请求转发给iframe中域名A的/util/ajaxrequest页面。

然后域名A中的/util/ajaxrequest页面处理请求:

如此实现后,发现iframe因为跨域问题无法加载

因为后端是由Django实现的,经过查阅发现,在views中需要进行处理,添加xframe_options_exempt装饰器,实现跨域加载iframe。

功能能够正常请求,但是请求中cookie并没有正常传送。

经过排查发现,对于跨域的iframe,google浏览器默认对于cookie中SameSite这个参数是LAX,会导致只有同源才能设置服务器返回的Set-Cookie。所以需要将服务器返回的Set-Cookie中指定SameSite为None,这样前端才能成功设置Cookie。

于是服务端Django引入了中间件django-cookies-samesite。settings.py进行如下修改:

至此实现了iframe方式跨域。

这个需要前端Jquery加入两个参数:

然后服务端需要开启跨域请求支持。Django下引入中间件django-cors-headers。settings.py下如下设置:

此方案也需要和iframe一样,解决cookie中SameSite的问题。

至此CORS方案跨域也实现了。

JQuery ajax jsonp 跨域理解

//简写形式

$.getJSON(\”http://app.example.com/base/json.do?sid=1494&busiId=101&jsonpCallback=?\”,

function(data){

$(\”#showcontent\”).text(\”Result:\”+data.result)

});

*/

$.ajax({

type : \”get\”,

async:false,

url : \”http://app.example.com/base/json.do?sid=1494&busiId=101\”,

dataType : \”jsonp\”,//数据类型为jsonp

jsonp: \”jsonpCallback\”,//服务端用于接收callback调用的function名的参数

success : function(data){

$(\”#showcontent\”).text(\”Result:\”+data.result)

},

error:function(){

alert(\’fail\’);

}

});

JSONP是JSON with Padding的略称,JSONP为民间提出的一种跨域解决方案,通过客户端的script标签发出的请求方式。

现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。

而所有非同源的请求(即 域名,协议,端口 其中一种或多种不相同),都会被作为跨域请求,浏览器会将其非同源的响应数据丢弃。

这里可以理解为是浏览器在搞事情,服务端确确实实有返回数据,浏览器接收到返回的数据,发现我们请求的是一个非同源的数据,浏览器再将其响应报文丢弃掉。

而通过一些标签发出的请求则不会被进行同源检查,比如script标签,img标签等等,本文讲述JSONP便是通过script标签做的请求。

例如:1、声明一个全局变量

window.myCallback = (res)=>{ //声明一个全局函数 \’callback\’,用于接收响应数据 console.log(res) }

2、发出请求

<script>

window.myCallback = (res)=>{//这里为上一步定义的全局函数

console.log(res)

}

</script>

<script url=\”xxx?callback=myCallback\”>

//script标签的请求必须在写在定义全局函数之后

//这里需将全局函数的函数名作为参数callback的value传递

//这里callback这个键名是前后端约定好的

</script>

原文链接:https://blog.csdn.net/weixin_44411976/java/article/details/100035936

3、服务端返回数据格式

myCallback({ //一个函数的调用,将数据作为参数传递进去,再将整个函数的调用返回给客户端 name:\’ahreal\’, age:18 })

4、客户端接收到服务端的相应,相当于:

<script>

window.myCallback = (res)=>{//这里为上一步定义的全局函数

console.log(res)

}

</script>

<script>//将接收到的数据作为script标签里面的内容展开执行

myCallback({

name:\’ahreal\’,

age:18

})

</script>

参数

jsonp

类型:String

在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 \”callback=?\” 这种 GET 或 POST 请求中 URL 参数里的 \”callback\” 部分,比如 {jsonp:\’onJsonPLoad\’} 会导致将 \”onJsonPLoad=?\” 传给服务器。

jsonpCallback

类型:String

为 jsonp 请求指定一个回调函数名。这个值将用来取代 jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。

如果不设置 jquery会自动调用seccess函数

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。