day24-JSONP跨域请求本质

一、前言

  我们之前访问的接口或者url 都是在自己本网站去访问,或者 提交 ,但是如果我要去调第三方接口,那怎么办,或者说我去调 其他 网站的接口,在我自己的网站去返回,这边就存在 跨域访问 ,这边是有限制的,所以,我们如何解决这个问题呢?我们比如说用  requests 这个模块去访问 接口的时候,会返回在 自己的web上:

from django.shortcuts import render
import requests
# pip install requests
# Create your views here.

def req(request):
    response = requests.get("http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=101121301")  #返回的是一个字节
    # print(response.text) #文本,这边把字节给转换了
    # print(response.cookies) # cookie
    # print(response.headers) # response_header
    response.encoding = "utf-8" #设置response变成utf-8变成字符串
    return render(request,'req.html',{'result': response.text})

原理图如下:

 说明这种方式是可以访问的,但是如果我们想要通过ajax 的形式跨域形式去访问呐,接下来我们就来讨论讨论。

二、JSONP存在的原因和原理

2.1、存在的原因

  由于浏览器具有同源(源指的是第三方域名)策略,你如果取别的域名请求,我浏览器直接就会给你阻止掉了,比如我们用 ajax 请求 第三方接口的话,就相当于直接阻止了 ajax的请求(Failed to load http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=101121301: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access.),但是无法阻止 含有src 属性标签的(<script crc='....'></script>),就是说所有含有src属性的标签,都不受到同源策略的影响。

2.2、实现jsonp的形式的条件

我们实现jsonp的形式的条件:

  1. 创建script 标签
  2. scr = 远程地址
  3. 返回的数据类型必须是js格式

只能发GET请求,不能是POST请求,就算是POST请求的话,也会转成GET请求的。

2.3、原理图

三、前提

  由于我们方便测试jsonp跨域,所以我们这边自己再另外建立一个  django project 项目,来模拟 第三方页面请求,所以我们新建的项目,并且设置本地hosts。操作步骤如下:

3.1、路由设置(urls.py)

说明:模拟第三方页面的url设置

from django.urls import path
from app01.views import accounts

urlpatterns = [
    path('jsonp.html/',accounts.jsonp),
]

3.2、jsonp函数编写

说明:模拟第三方页面的函数编写

from django.shortcuts import HttpResponse
def jsonp(request):
    """
    测试jsonp的请求接口
    :param request:
    :return:
    """
    print(request.GET)
    return HttpResponse('alert(1000)')

3.3、添加 hosts

说明:这个可以用本地hosts添加绑定域名

127.0.0.1 zhangqigao.com 

3.4、需要添加白名单

说明:通过域名访问模拟第三方页面,需要在第三方项目  settings.py文件中添加白名单

ALLOWED_HOSTS = ['zhangqigao.com','127.0.0.1',] # add white name table

四、JSONP请求跨域

  我们创建本地项目,然后我们这边有些东西是不变的,比如url和函数,修改的只是模板,因为只是通过 原生ajax 或者 添加标签方式,或者用 jquery的方式去访问,所以我这边的url 和 req函数我就直接写了

4.0、前提

路由设置(url):

from django.urls import path
from app02 import views as a2

urlpatterns = [
    path('req/',a2.req)
]

req函数:

def req(request):
    return render(request,'req.html')

4.1、原生ajax跨域请求

说明:我们知道原生ajax调第三方接口的时候,去自己的浏览器去显示的时候,本地浏览器是拒绝的,并且会给你一个拒绝的提示,因为它受到同源策略的影响,这边就直接写 req.html就行了

<body>
    <input type="button" value="获取数据" οnclick="getContent();">
    <script>
        function getContent() {
            var xhr = new XMLHttpRequest();
            //xhr.open('GET','http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=101121301'); //天气接口
            xhr.open('GET', 'http://zhangqigao.com:8080/jsonp.html?k1=v1&k2=v2'); //模拟第三方接口,这边通过get传入 k1和k2
            xhr.onreadystatechange = function () {
                console.log(xhr.responseText);
            };
            xhr.send();
    </script>
</body>

我们来看一下效果,正是因为受到同源策略的影响,所以我们在接收请求的时候,浏览器是拒绝的,拒绝的效果图如下:

4.2、创建script标签方式跨域请求

说明:我们知道所有带src属性的标签都不收同源策略的影响,所以我们通过这种方式来看一下,看一下这种方式是怎么实现的。

<body>
    <!--
    <h1>后台获取的结果</h1>
    {{ result }}
    <h1>js直接获取结果</h1>
    -->
    <input type="button" value="获取数据" οnclick="getContent();">
    <script>
        function getContent() {
            var tag = document.createElement('script');
            tag.src = "http://zhangqigao.com:8080/jsonp.html?callback=list&k2=v2"; //请求模拟第三方页面
            document.head.appendChild(tag);     
        }
    </script>
</body>

我们现在看看能不能接受到请求过来的参数,因为我们说,这边只接收 js形式的,所以是字符串形式的我们就不测试了,所以我们下面来看看:

我靠,这边确实没有收到同源策略的影响,但是我们这边只接收了一个alert,那我如果接收一个callback函数,并且定义传过来的函数不就行了,那我的模拟第三方的jsonp函数代码如下:

from django.shortcuts import HttpResponse
def jsonp(request):
    """
    测试jsonp的请求接口
    :param request:
    :return:
    """
    print(request.GET)
    # return HttpResponse('alert(1000)')
    # return HttpResponse('callbakc(1000)')

    func = request.GET.get('callback') #callback = list
    content = '%s(1000)'%(func,)  # list(1000)
    return HttpResponse(content) # 返回 content=list(1000)

我的本地的req.html改进:

<body>
    <input type="button" value="获取数据" οnclick="getContent();">
    <script>
            var tag = document.createElement('script');
            tag.src = "http://zhangqigao.com:8080/jsonp.html?callback=list&k2=v2";  //一般情况传入的都叫callback
            //tag.src = "http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403";  //这个是某个天气的接口,这个可以测试,是一样的
            document.head.appendChild(tag);
            document.head.removeChild(tag); //不能无限的添加,只要我把值传过来,我就立马删掉就行了

        }

        function list(args){  //通过callback=list参数,如果不写的话,浏览器会报 list is not defind,所以要定义 list函数
            console.log(args); //args就是接收第三方的list(1000)中1000这参数,也就是说这边 args = 1000
        }
    </script>
</body>

实现的效果图:

tag.src = "http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403"; //这个是某个天气的接口,这个可以测试,是一样的,这边测试一下结果:

4.3、Jquery跨域请求方式

说明:jquery的跨域的本质原理跟上面 通过创建 script是一样的,我们用的时候首选用jquery这种方式,也是快速加一个script标签,然后又把新增的script的标签删掉。

<body>
    <!--
    <h1>后台获取的结果</h1>
    {{ result }}
    <h1>js直接获取结果</h1>
    -->
    <input type="button" value="获取数据" οnclick="getContent();">
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function getContent() {
            $.ajax({
                url:'http://www.jxntv.cn/data/jmd-jxtv2.html?_=1454376870403',
                type: 'GET', //这边写POST也行,反正是最后还是要转成GET的,我们这边就直接写成GET
                dataType: 'jsonp',
                jsonp:'callback',
                jsonCallback:'list'
                //jsonp和jsonCallback合起来表示:http://url?callback=list的效果
            })
        }

        function list(args){
            console.log(args);
        }
    </script>
</body>

测试过了,跟上面的效果是一模一样啊,这个就是jquery请求方式。更多跨域方式:http://www.cnblogs.com/wupeiqi/articles/5369773.html  3.文档处理->6.ajax 跨域

4.4、cors

说明:这个东西不是经常用,常用的还是我们上面的通过jquery的方式,但是我们知道有这么一个东西,随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。

更多详细资料:https://www.cnblogs.com/wupeiqi/articles/5703697.html 中的  跨域ajax

五、总结

  1、jsonp跨域请求方式 只能是 GET 方法 就算是POST方法也会转成GET方法

  2、我们实现jsonp的形式的条件:

  • 创建script 标签
  • scr = 远程地址
  • 返回的数据类型必须是js格式

  3、跨域还可以用jquery的方式,当然还可以是 cors,只是我们用的最多的是 jquery方式 ,但是原理还是 第2种

 

转载于:https://www.cnblogs.com/zhangqigao/articles/9068187.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值