zoukankan      html  css  js  c++  java
  • 同源策略

    1.  Jquery 对象可以通过 .index() 进行取出自当前元素在父级元素中存放的索引;

    2. 浏览器的同源策略 -- Ajax 在访问非本网站的时候,在数据返回的时候,会被浏览器拦截

       - 后端使用 requests 获取数据后,发送给前端

       - jsonp 在前端页面中, 带有 src 属性的标签不受同源策略的影响(img, script, iframe等),我们可以通过使用 script 标签来获取内容,但 script 中 src 获取内容后,获得到的字符串(类似于调用python中的 eval 或 exec)会被 JS 执行,所以我们可以定义一个函数,然后让服务端返回的内容外面包裹一层这个函数名,前端在访问的时候把这个函数名发送过去,并提前定义好该函数

    手动实现:

    服务端返回的数据

    def server(request):
    
        return HttpResponse("aaa('important data!!!')")
    

    客户端定义及获取数据

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Client</title>
        <script src="/static/jquery-3.2.1.js"></script>
        <script>
            $(function(){
    
            });
    
            var url = 'http://127.0.0.1:8000/server.html/';  // 服务端路径
            var $script;                                     // 模拟使用创建的标签名
            function aaa(data){                              // 数据返回后用来接收的函数
                alert(data);
                document.head.removeChild($script);          // 接收完数据后,从页面删除刚才使用的标签
            }
            function getInfo(){
                $script = document.createElement("script");  // 创建一个 script 标签
                $script.setAttribute("src", url);            // 将需要请求数据的地址放入 script 的 src 中
                document.head.appendChild($script);          // 将标签放入到 head 中
    
            }
    
        </script>
    </head>
    <body>
        <h1>Client</h1>
        <input type="button" onclick="getInfo()" value="getInfo">
    </body>
    </html>
    

    通过JSONP自动完成 - 上面是它的原理

     服务端返回的数据

    from django.shortcuts import render
    from django.http import HttpResponse, JsonResponse
    
    def server(request):
        # 根据后端发送过来的名字来决定返回时,数据外面套的内容
        funcName = request.GET.get("callback")
        return HttpResponse("%s('important data!!!')"%funcName)
    

      客户端定义及获取数据

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Client</title>
        <script src="/static/jquery-3.2.1.js"></script>
        <script>
            function bbb(data){
                alert(data);
            }
    
            $(function(){
                var url = 'http://127.0.0.1:8000/server.html/';  // 服务端路径
                $.ajax({
                    url: url,                   // 跨站请求数据的路径
                    type: 'GET',                // 发送方式为 get, 由于使用的是 script, 所以只支持 get
                    dataType: 'JSONP',          // 使用 JSONP 方式
                    jsonp: 'callback',          // get 发送的时候,后面跟的数据名为 callback
                    jsonpCallback: 'bbb'        // get 发送数据的callback的值为 bbb
                })
            });
    
        </script>
    </head>
    <body>
        <h1>Client</h1>
        <input type="button" value="getInfo">
    </body>
    </html>
    

     

    cors - 跨域资源共享 cross origin resource sharing

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

      cors 分为简单请求和非简单请求,简单请求只发送一次,直接发送数据,非简单请求则会发送两次数据,第一次发送 opption 请求(预检),为的是查看真正的数据是否可以被接收(数据头和请求方式是否符合要求), 如果符合要求,服务端可以把内容加入到头文件中来告诉浏览器;

    简单请求与非简单请求

    条件:
        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
    

      

    简单请求:在使用cors的时候,客户端几乎不用修改,只需要按照普通的ajax的请求方式发送,在服务端返回数据的时候,只要在返回的时候,加上一个响应头就可以解决这个问题了

    def example(request):
        response = HttpResponse("返回的数据内容")
        response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8888"  # 允许访问获取信息的域名
        return response
    

      服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*',允许访问获取信息的域名,如果后面是*的话,代表允许所有的请求,如果需要每一个相应都设置该响应头的话(即这个网站的所有资源都可以被其它域名的所访问,那么我们可以在中间件中设置这个响应头);

    对于复杂请求,会先发一次预检(OPTIONS)请求,如果服务端允许,那么再发送一次正式请求(如PUT等,总之就是正真的请求),这个时候,我们需要在后端进行判断,如果允许用户获取数据,那么当预检(OPTIONS)过来的时候,我们需要返回允许访问的请求:Access-Control-Allow-Methds

    if request.method == "OPTIONS":
        response = HttpResponse() // 返回的内容可以为空,主要需要返回请求头
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'PUT'   # 允许的复杂请求方式为 PUT 请求;如果多个,用逗号分隔, "PUT, DELETE"
        response['Access-Control-Allow-Headers'] = "k1"  # 复杂请求还有一种情况就是定制请求头,这种情况下,我们在返回的相应中应该设置该响应头,代表允许发送请求头的key是什么,如果多个,逗号分隔 "k1, k2"
        return response
    

      如果我们不想每次都经过“预检”这个环节的话,那么我们可以在服务器的响应头中增加一组:Access-Control-Max-Age的响应头,可以写成

    response['Access-Control-Allow-Headers'] = 10  # 默认单位为秒
    

      

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <meta http-equiv="x-ua-compatible" content="IE=edge">
     6     <meta name="viewport" content="width=device-width, initial-scale=1">
     7     <title>Title</title>
     8     <script src="/static/jquery-3.2.1.js"></script>
     9     <script>
    10         $(function(){
    11             $("#btn01").click(function(){
    12                 $.ajax({
    13                     url: "http://127.0.0.1:8000/btn01/",
    14                     success: function(data){
    15                         console.log(data)
    16                     }
    17                 })
    18             });
    19 
    20             $("#btn02").click(function(){
    21                 $.ajax({
    22                     url: "http://127.0.0.1:8000/btn02/",
    23                     type: "PUT",
    24                     success: function(data){
    25                         console.log(data)
    26                     }
    27                 })
    28             });
    29 
    30             $("#btn03").click(function(){
    31                 $.ajax({
    32                     url: "http://127.0.0.1:8000/btn03/",
    33                     headers: {"k1": "asdfasdf"},
    34                     success: function(data){
    35                         console.log(data)
    36                     }
    37                 })
    38             })
    39         })
    40     </script>
    41 </head>
    42 <body>
    43 <p><input type="button" value="简单请求" id="btn01"></p>
    44 <p><input type="button" value="复杂请求-PUT" id="btn02"></p>
    45 <p><input type="button" value="复杂请求-Headers" id="btn03"></p>
    46 </body>
    47 </html>
    简单和复杂请求的客户端代码
     1 from django.shortcuts import render
     2 from django.http import HttpResponse
     3 
     4 # Create your views here.
     5 def btn01(request):
     6     response = HttpResponse("btn01")
     7     response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8888"
     8     return response
     9 
    10 
    11 def btn02(request):
    12     if request.method == "OPTIONS":
    13         response = HttpResponse()
    14         response['Access-Control-Allow-Origin'] = '*'
    15         response['Access-Control-Allow-Methods'] = 'PUT'
    16         return response
    17 
    18     if request.method == "PUT":
    19         response = HttpResponse("btn02")
    20         response['Access-Control-Allow-Origin'] = '*'
    21         return response
    22 
    23 
    24 def btn03(request):
    25     if request.method == "OPTIONS":
    26         response = HttpResponse()
    27         response['Access-Control-Allow-Origin'] = '*'
    28         response['Access-Control-Allow-Headers'] = "k1"
    29         return response
    30 
    31     if request.method == "GET":
    32         response = HttpResponse("btn03")
    33         response['Access-Control-Allow-Origin'] = '*'
    34         return response
    简单和复杂请求的服务端代码

    携带cookie的传输

    如果在使用Ajax请求的时候,需要传递cookie的时候,我们则需要在发送ajax的时候,以及服务器给我们相应的时候加上一组头信息

    客户端需要加:XMLHttpRequest的withCredentials为true

    $.ajax({
        url: "http://c2.com:8000/test/",
        type: 'PUT',
        dataType: 'text',
        headers: {'k1': 'v1'},
        xhrFields:{withCredentials: true},  // 加在了这里
        success: function(data, statusText, xmlHttpRequest){
            console.log(data);
        }
    })
    

      

    服务端需要加:Access-Control-Allow-Credentials为true

    class MainHandler(tornado.web.RequestHandler):
        
        def put(self):
            self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
            self.set_header('Access-Control-Allow-Credentials', "true")   # 加在了这里
            
            self.set_header('xxoo', "seven")
            self.set_header('bili', "daobidao")
            self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
    
            self.set_cookie('kkkkk', 'vvvvv');
    
            self.write('{"status": true, "data": "seven"}')
    
        def options(self, *args, **kwargs):
            self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
            self.set_header('Access-Control-Allow-Headers', "k1,k2")
            self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
            self.set_header('Access-Control-Max-Age', 10)
    

      

    http://www.cnblogs.com/wupeiqi/articles/5703697.html

    3. 模拟点击事件

    $("#a").trigger("chick"); // 模拟执行 id=a 的事件

  • 相关阅读:
    强化学习
    详解a标签中href=""的几种用法 锚点
    使用Django自带的登录访问限制login_required
    ValueError: invalid literal for int() with base 10: ''
    Django 中创建Model时报以下错误: TypeError: init() missing 1 required positional argument: ‘on_delete’
    bootstrp实现同一界面多个模态框
    第十二章 Django框架开发
    Python format 格式化函数
    Python3.x在django中如何设置Content-Disposition,才能让浏览器正确保存中文命名的文件?
    python中的*和**参数传递机制
  • 原文地址:https://www.cnblogs.com/alwaysInMe/p/7686931.html
Copyright © 2011-2022 走看看