为了更好的解释JSONP跨域请求的本质,我们先通过Python的爬虫请求模块requests,来看一下有什么效果。requests模块的功能就是请求url然后返回response信息,我们还是使用Django来实现。创建req路由规则,通过requests.get向某个数据API接口发送请求,并返回response,将response.text文本展示在req的url中,具体实现:
import requests
def req(request):
response=requests.get('https://www.iconfont.cn/api/common/indexConfig.json?t=1588556274895&ctoken=B4ftU3SA5676hkHnZaBJRi9f')
html=response.content.decode()
return render(request,'req.html',{'html':html})
以上代码请求的是一个iconfont图标的api接口,html是接口的数据,我们传递到req.html页面中并展示出来,其它地方自行配置好,那么我们可以看到没什么问题,数据呈现在网页中,并且浏览器的控制台也没有错误信息。
这种方式是通过requests去请求数据接口,然后放到我们的django服务端。我们试试直接通过django的服务器去获取数据,会发生什么。接下来在req.html页面搞个按钮,并绑定js事件,点击就会访问api接口:
<input type="submit" onclick="getContent();" value="js获取">
<script>
function getContent() {
var xhr=new XMLHttpRequest();
xhr.open('GET','https://www.iconfont.cn/api/common/indexConfig.json?t=1588556274895&ctoken=B4ftU3SA5676hkHnZaBJRi9f');
xhr.onreadystatechange=function(){
conslole.log(xhr.responseText)
};
xhr.send();
}
</script>
现在运行django服务端,然后点按钮请求数据,那么就成功的触发了下图的报错信息:

英文报错:No ‘Access-Control-Allow-Origin’ header is present on the requested resource.,翻译过来就是已被CORS策略阻止:请求的资源上不存在“Access Control Allow origin”头。
其实我们呢在点击按钮的时候已经成功的向数据接口发送信息,并且对方已经吧数据给我们了,但是被浏览器拒绝了,这是由于浏览器的同源策略,它不允许你向其它域名发送ajax请求。鳄鱼君Ba提供了一下三种方式来解决:
通过jsonp处理跨域(基于原生js)
注意:jsonp只能模拟get请求处理跨域1、jsonp介绍
jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。下面介绍一个jsonp基本实现原理,即利用script特性实现跨域请求,如下实例:
2、基于JS的JSONP的实现一般情况下,我们希望这个script标签能够动态的调用,我们可以通过页面的触发事件操作后,通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务。实例如下:
前面的两种方式进行对比,你就会发现真的是浏览器阻止了对方返回的数据。第一种是使用requests请求数据接口,返回并展示在浏览器中,浏览器只是参与了展示信息;第二种是通过ajax的xhr对象发送请求,这个过程了是借助浏览器来发送请求的,但是数据被阻止了。解决办法很简单,浏览器会阻止Ajax请求,但是不会阻止通过script标签发送的请求,这是前辈们说的,我也不知道,所以试试看:
<input type="submit" onclick="getContent();" value="js获取">
<script>
function getContent() {
var tag=document.createElement('script'); //创建script标签
tag.src='http://e1yu.com:8000/res/?k1=name&k2=age'; //设置src属性
document.head.appendChild(tag); //将script标签添加到head中
document.head.removeChild(tag);//将script标签移除
}
</script>
修改代码后运行django服务端,那么又一次非常开心的看到浏览器又给了一些提示Cross-Origin Read Blocking (CORB) blocked cross-origin response https://xxx with MIME type application/json.(跨源读取阻塞(CORB)用MIME类型application/json阻塞了跨源响应https://xxx。),前面其实还有一个错误:A cookie associated with a cross-site resource at https://www.iconfont.cn/ was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. (与https://www.iconfont.cn/上的跨站点资源关联的cookie未设置“SameSite”属性。如果Chrome的未来版本设置为“SameSite=None”和“Secure”,则它只能传递带有跨站点请求的cookie)。
<input type="submit" onclick="getContent();" value="js获取">
<script>
function sendMsg2() {
var tag = document.getContent('script');
tag.src = 'http://127.0.0.1:8001/api/?callback=list';
document.head.appendChild(tag);
document.head.removeChild(tag);
}
// 动态回调函数
function list(arg) {
console.log(arg);
}
</script>
为了更加灵活,可以自己在客户端定义一个回调函数,然后将函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调。这里你需要使用django创建两个服务端才可以。一般来说所有的网站都是这样使用的,你可以自己尝试一下。
from django.shortcuts import render, HttpResponse
def api(request):
# 获取查询字符串中的callback参数
func_name = request.GET.get('callback')
return HttpResponse('%s("baidu.com")' % func_name)
通过jsonp处理跨域(基于jQuery中的getJSON方法)
基于jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法。与js实现的方式相比,我们并不要自己生成一个script标签,客户端也并不需要自己定义一个回调函数,要注意的是在$.getJSON(url,[data],[callback])方法的url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。
<input type="submit" class="ajax_btn" value="getjson获取">
<script>
$(".ajax_btn").click(function () {
$.getJSON("http://127.0.0.1:8001/api/?callback=list",function (data) {
console.log(data);
})
});
</script>
项目中的视图函数,即跨域请求的路径
def res(request):
import json
func_name=request.GET.get("callback") #获得回调函数的名字
return HttpResponse("%s('123')" % func_name)
通过jsonp处理跨域(基于jQuery中的ajax方法)
上述这种方法,很方便,不需要我们自己定义回调函数和指定回调函数名,但是,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现。如下例:
<input type="submit" class="ajax_btn" value="getjson获取">
<script>
$(".ajax_btn").click(function () {
$.ajax({
url:"http://127.0.0.1:8001/api/",
dataType:"jsonp", //相当于script标签
jsonp:'callbacks', //相当于路径中回调函数路径参数键值对的键
jsonpCallback:"func" //相当于路径中回调函数路径参数键值对的值,回调函数名
})
});
//定义回调函数
function func(arg) {
console.log(arg);
}
</script>
项目中的视图函数,即跨域请求的路径
def res(request):
func_name=request.GET.get("callbacks") #获得回调函数的名字
return HttpResponse("%s('123')" % func_name)
django-cors-headers实现防跨域
测试失败…待更新呢 1.安装cors模块pip install django-cors-headers
2.修改setting.py中配置INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
3.添加允许访问的白名单,凡是出现在白名单的域名都可以访问后端接口
CORS_ORIGIN_WHITELIST = (
'127.0.0.1:8080',
'localhost:8080',
)
CORS_ALLOW_CREDENTIALS = True # 指明在跨域访问中,后端是否支持对cookie的操作。
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
CorsMiddleware应该放置得尽可能高,特别是在可以产生响应的任何中间件之前, 如Django CommonMiddleware或Whitenoise WhiteNoiseMiddleware。 如果以前没有,则无法将CORS头添加到这些响应中。
暂且先整理,鳄鱼君Ba在django中测试的时候一直没有解决cors问题,待更新…….
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!