跨域AJAX

由于浏览器存在同源策略,同源策略指:浏览器 对不同源的脚本或文本的访问方式 进行的限制。比如源a的js不能读取或设置引入的源b的元素属性。

(阻止从一个源 加载文档 或脚本获取 或设置  另一个源 加载的文档的属性)。

定义同源:就是指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可。

由于同源策略是浏览器的限制,所以请求的发送和响应是 可以进行,只不过浏览器不接受而已。

浏览器的同源策略并不是对所有的请求都制约:

  制约:XmlHttpRequest

  允许:img,script 等具有 src属性的标签

跨域名访问,如: http://www.c1.com域名 向 http://www.c2.com域名发送请求。

1.JSONP实现跨域请求

JSONP(JSONP - JSONP with Padding 是JSON的一种 ‘使用模式’),利用script标签的src属性(浏览器允许script标签跨域)

远程:

views.py

def get_data(request):
    import time
    time.sleep(3)
    func_name = request.GET.get('callback')
    return HttpResponse('%s("机密数据123")'%func_name)
View Code

本地:

views.py

def index(request):

    return render(request,'index.html')
View Code

index.html

<body>

    <h1>江山如此多娇</h1>
    <div id="i1"></div>

     <input type="button" onclick="jsonp('http://127.0.0.1:8001/get_data.html?callback=funcvv')"  value="发送JSONP请求"/>
    <input type="button" onclick="Jsonp2()" value="发送JSONP2请求">
    <input type="button" onclick="Jsonp3()" value="发送JSONP3请求">

    <script src="/static/jquery-3.2.1.js"></script>
    <script>


        /*
        手动实现jsonp
         */

        function funcvv(arg) {

            alert(arg);

        }
        function jsonp(url) {
            tag = document.createElement('script');
            tag.src = url;
            document.head.appendChild(tag);
        }



        function Jsonp2() {
            $.ajax({
                url:'http://127.0.0.1:8001/get_data.html',
                type:'GET',
                dataType:'JSONP',
                success:function (data) {
                    console.log(data);
                }

            })
        }



        function list(arg) {
            console.log(arg);
        }
         function Jsonp3(){
            $.ajax({
                url: "http://127.0.0.1:8001/get_data.html",
                type: 'GET',
                dataType: 'JSONP',
                jsonp: 'callback',
                jsonpCallback: 'list'
            })
        }
    </script>

</body>
View Code

笔记:

- JSONP:
        本地:先定义函数
        远程:func("数据")
        
        方式一:手动
                /*
                function funcvvvvvv(arg) {
                    alert(arg);

                    document.head.removeChild(tag);
                }

                function jsonp(url){
                    tag = document.createElement('script');
                    tag.src = url;
                    document.head.appendChild(tag);
                }*/
        方式二:调用jQuery
                function Jsonp2(){
                    $.ajax({
                        url: "http://127.0.0.1:8000/get_data.html",
                        type: 'GET',
                        dataType: 'JSONP',
                        success: function(data){
                            console.log(data);
                        }
                    })
                }
        本质:创建script标签    

        编写跨域请求:
            本地:
                
                function list666(arg){
                
                }
                
                $.ajax({
                    url: "http://www.jxntv.cn/data/jmd-jxtv2.html",
                    type: 'GET',
                    dataType: 'JSONP',
                    jsonp: 'callback',
                    jsonpCallback: 'list666'
                })
                
            远程:
                func_name = request.GET.get('callback')
                return HttpResponse('%s("机密数据")' %func_name)
View Code

2.CORS

现在浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,是的浏览器允许跨域请求。

 解决方法:

-------远程
def cors_data(request):

    response = HttpResponse('机密数据333')
    # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #设置某个能访问的域名
    response['Access-Control-Allow-Origin'] = '*'    #所有

    return response



--------本地
views.py

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



.HTML
<body>

     <h1>大浪淘沙</h1>
     <script src="/static/jquery-3.2.1.js"></script>

     <script>

         $.ajax({
             url:'http://127.0.0.1:8001/cors_data.html',
             type:'GET',
             success:function (data) {
                 console.log(data);
             }
         })
     </script>
</body>
GET方式

 从而引出:

*简单请求 OR 非简单请求

条件:
    1、请求方式:HEAD、GET、POST
    2、请求头信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 对应的值是以下三个中的任意一个
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求





*简单请求和非简单请求的区别?
    
简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。




* 关于“预检”

- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
     => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
     => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers

PUT方法请求(非简单):

----远程

def cors_data(request):

    if request.method == 'OPTIONS':
        #预检
        response = HttpResponse() #可为空
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'PUT'
        return response

    elif request.method == 'PUT':
        response = HttpResponse('机密数据333')
        # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #设置某个能访问的域名
        response['Access-Control-Allow-Origin'] = '*'    #所有

        return response




-------本地

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



<body>

     <h1>大浪淘沙</h1>
     <script src="/static/jquery-3.2.1.js"></script>

     <script>

         $.ajax({
             url:'http://127.0.0.1:8001/cors_data.html',
             type:'PUT',  #------PUT------
             success:function (data) {
                 console.log(data);
             }
         })
     </script>
PUT

 GET + 自定义headers(非简单):

--------远程

def cors_data(request):

    if request.method == 'OPTIONS':
        #预检
        response = HttpResponse() #可为空
        response['Access-Control-Allow-Origin'] = '*'
        # response['Access-Control-Allow-Methods'] = 'PUT'
        response['Access-Control-Allow-Headers'] = 'xxx'    # 自定义的 headers:{'xxx':333},
        return response

    elif request.method == 'GET':
        response = HttpResponse('机密数据333')
        # response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000' #设置某个能访问的域名
        response['Access-Control-Allow-Origin'] = '*'    #所有

        return response





-------本地
def index_cors(request):
    return render(request,'index_cors.html')


.HTML
<body>

     <h1>大浪淘沙</h1>
     <script src="/static/jquery-3.2.1.js"></script>

     <script>

         $.ajax({
             url:'http://127.0.0.1:8001/cors_data.html',
             type:'GET',
             headers:{'xxx':333},
             success:function (data) {
                 console.log(data);
             }
         })
     </script>
</body>
View Code

#补充:

  JSONP:具有兼容性

  CORS(早期有些浏览器版本,不支持)

  不到不得已,才让发 非简单请求(会增加服务器压力)

例如:

 笔记:

本地:无作为
            远程:设置响应头
                    response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8888"
                    response['Access-Control-Allow-Methods'] = "PUT"
                    response['Access-Control-Allow-Headers'] = "xxx"
                          
View Code
原文地址:https://www.cnblogs.com/zhaochangbo/p/7538966.html