zoukankan      html  css  js  c++  java
  • Django-解决跨域请求(基于js,jQuery的josnp,设置响应头的cors)

    同源策略

    同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

    同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

    url http ip port paht ? 数据
      if 协议 IP PORT相同,同源

    一,问题描述

    1 django 创建2个项目 
    2 项目一,开启一个send_ajax请求  http://127.0.0.1:8000
    3 访问正常
    4 
    5 项目二,没有send_ajax请求  http://127.0.0.1:8010
    6 那么这时候如果你通过ajax访问的 url:http://127.0.0.1:8000/send_ajax
    7 浏览器会报错,内容是已拦截跨域请求,同源策略禁止读取位于http://127.0.0.1:8000/send_ajax远程资源,原因:cors头缺少 ‘Access-Control-Allow-Origin’

    1.1 思考

    jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

    1 跨域请求:
    2       ajax请求一定会被拦截
    3 
    4 核心任务:跨域请求的是数据,数据,数据
    5 
    6 通过引入jquery cdn 可以跨域 我们想 是不是script标签不会被拦截呢?
    7 <script src=" https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>

    1.2跨域请求的演变

     1 项目一 views
     2 import json
     3 def send_ajax(request):
     4     return HttpResponse("yuan")          # 第一次返回字符串
     5     return HttpResponse("yuan()")        # 第二次返回函数字符串   
     6     return HttpResponse("yuan('yuan')")   # 第三次返回函数参数字符串
     7     s='hello world'    
     8     return HttpResponse("yuan('%s')"%s)   # 第四次返回函数字符串数据
     9     
    10     s={"name":"egon","age":122}          
    11     return HttpResponse("%s('%s')"%(func_name,json.dumps(s))) # 第五次返回函数json字符串
    12     
    13 项目二 html
    14 第一次字符串,你要是知道数据是什么还请求干什么?所以这里只是个引子,告诉你可以这样做
    15 <script>yuan</script>
    16 <script src="http://127.0.0.1:8000/send_ajax"></script>
    17 
    18 
    19 第二次函数字符串
    20 <script>function yuan(){alert(123)}</script>
    21 <script src="http://127.0.0.1:8000/send_ajax"></script>
    22 
    23 
    24 第三次返回函数参数字符串
    25 <script>function yuan(arg){alert(arg)}</script>
    26 <script src="http://127.0.0.1:8000/send_ajax"></script>
    27 
    28 
    29 第四次返回函数字符串数据(数据也是字符串)
    30 <script>function yuan(arg){alert(arg)}</script>
    31 <script src="http://127.0.0.1:8000/send_ajax"></script>
    32 
    33 
    34 第五次返回函数json字符串
    35 <script>function yuan(arg){alert(Json.parse(arg))}</script>
    36 <script src="http://127.0.0.1:8000/send_ajax"></script>

    1.3问题

    1 我不能硬生生的将<script src="http://127.0.0.1:8000/send_ajax"></script>写在html里面,我需要动态创建下面的函数

       我们通过触发点击事件函数创建

     1 <script>
     2     function yuan(arg) {
     3         console.log(arg);
     4         console.log(JSON.parse(arg));
     5     }
     6 </script>
     7 
     8 <script>
     9     $(".send_ajax").click(function () { 
    10        kuayu_request("http://127.0.0.1:8000/send_ajax/")
    11     });
    12     function kuayu_request(url) {
    13         var $script=$("<script>");  // 创建script标签,是一个jquery对象: <script>
    14         $script.attr("src",url);
    15         $("body").append($script);
    16         $("body script:last").remove();
    17     }
    18 </script>

    1.4 问题

    1 1 问题函数名字是不是可以通过请求传送到后端呢?应该是同步的,可否通过回调函数?

      可以通过发送请求的时候带着数据,数据包含你的函数名称,这样传到后端,再让后端返回你这个函数和数据,就可以执行了

     1 项目二 html
     2 <script>
     3     $(".send_ajax").click(function () { 
     4        kuayu_request("http://127.0.0.1:8000/send_ajax/?callback=bar")
     5     });
     6     function kuayu_request(url) {
     7         var $script=$("<script>");  // 创建script标签,是一个jquery对象: <script>
     8         $script.attr("src",url);
     9         $("body").append($script);
    10         $("body script:last").remove();
    11     }
    12 </script>
    13 
    14 
    15 项目一 views
    16 def send_ajax(request):
    17     func_name = request.GET.get('callback')
    18     s = 'hello'
    19     return HttpResponse("%s('%s')"%(func_name,json.dump(s)))

    之前都是引子,下面才是真正的用法。。

    ajax的跨域请求写法

     1 <script>
     2 
     3     $(".send_ajax").click(function () {
     4 
     5         $.ajax({
     6             url:"http://127.0.0.1:8000/send_ajax/",
     7             success:function (data) {
     8                 alert(data)
     9             },
    10             // 跨域请求  <script>  告诉服务器我要什么类型的数据contenttype是告诉服务器我是什么类型数据
    11             dataType:"jsonp",
    12             jsonp: 'callbacks', //?callbacks=SayHi 相当于这个,问题就是在于前后端的函数名要相同
    13             jsonpCallback:"SayHi"
    14         })
    15 
    16 
    17     });
    18 
    19     function SayHi(arg) {
    20         console.log("hello",arg)
    21     }
    22 </script>
    23 
    24 {#// ==========================================基于jquery的JSONP的实现3 (推荐)#}
    25 
    26 <script>
    27 
    28     $(".send_ajax").click(function () {
    29 
    30         $.ajax({
    31             url:"http://127.0.0.1:8000/send_ajax/",
    32             dataType:"jsonp",   // 跨域请求  <script>
    33             // callbacks=? ?就是随机字符串了,后端传回来运行的就是success函数,也就是funciton 函数参数是数据
    34             jsonp: 'callbacks',
    35             success:function (data) {
    36                 console.log(data)
    37             }
    38         })
    39 
    40     });
    41     
    42 </script>

    jsonp的所有实现和应用例子

    项目一的views.py

    1 import json
    2 def send_ajax(request):
    3     s={"name":"egon","age":122}
    4     return HttpResponse("list('%s')"%json.dumps(s))
    View Code

    项目二的index.html

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5     <title>Title</title>
      6     <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
      7 </head>
      8 <body>
      9 <h1>项目2的首页</h1>
     10 <button class="send_ajax">send_ajax</button>
     11 
     12 
     13 {#// ==========================================基于JS的JSONP的实现#}
     14 <script>
     15     function bar(arg) {
     16        console.log(arg);
     17        console.log(JSON.parse(arg));
     18     }
     19 </script>
     20 
     21 <script>
     22 
     23     $(".send_ajax").click(function () {
     24        kuayu_request("http://127.0.0.1:8000/send_ajax/?callback=bar")  // 回调函数
     25     });
     26     // 创建script添加scr属性,获取数据
     27     function kuayu_request(url) {
     28         var $script=$("<script>");  // 创建script标签,是一个jquery对象: <script>
     29         $script.attr("src",url);
     30         $("body").append($script);
     31         $("body script:last").remove();
     32     }
     33 
     34 </script>
     35 
     36 
     37 <hr>
     38 
     39 {#// ==========================================基于jquery的JSONP的实现1#}
     40 
     41 
     42 <script>
     43 
     44    $(".send_ajax").click(function () {
     45         // getJSON帮助我们创建了script标签和src属性 ,还有个参数,data= 可以写入一些给后端的字符串
     46        // 匿名函数,函数会有getJSON创建随机字符串也就是callbacks=?的问好的值,函数参数的data是数据
     47       $.getJSON("http://127.0.0.1:8000/send_ajax/?callbacks=?",function (data) {
     48          console.log(data)
     49       })
     50    })
     51 
     52 </script>
     53 
     54 
     55 {#// ==========================================基于jquery的JSONP的实现2#}
     56 
     57 <script>
     58 
     59     $(".send_ajax").click(function () {
     60 
     61         $.ajax({
     62             url:"http://127.0.0.1:8000/send_ajax/",
     63             success:function (data) {
     64                 alert(data)
     65             },
     66             // 跨域请求  <script>  告诉服务器我要什么类型的数据contenttype是告诉服务器我是什么类型数据
     67             dataType:"jsonp",   
     68             jsonp: 'callbacks', //?callbacks=SayHi 相当于这个,问题就是在于前后端的函数名要相同
     69             jsonpCallback:"SayHi"
     70         })
     71 
     72 
     73     });
     74 
     75     function SayHi(arg) {
     76         console.log("hello",arg)
     77     }
     78 </script>
     79 
     80 {#// ==========================================基于jquery的JSONP的实现3 (推荐)#}
     81 
     82 <script>
     83 
     84     $(".send_ajax").click(function () {
     85 
     86         $.ajax({
     87             url:"http://127.0.0.1:8000/send_ajax/",
     88             dataType:"jsonp",   // 跨域请求  <script>
     89             // callbacks=? ?就是随机字符串了,后端传回来运行的就是success函数,也就是funciton 函数参数是数据
     90             jsonp: 'callbacks',  
     91             success:function (data) {
     92                 console.log(data)
     93             }
     94         })
     95 
     96     });
     97 
     98 
     99 </script>
    100 
    101 {#// =========================================应用#}
    102 
    103 
    104 <script>
    105 
    106     $(".send_ajax").click(function () {
    107 
    108         $.ajax({
    109             url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403",
    110             dataType:"jsonp",
    111             jsonp:"callback",
    112             jsonpCallback:"list"
    113         })
    114 
    115 
    116     });
    117 
    118     function list(shuju) {
    119           console.log(shuju.data);  // {data: Array(7)}
    120           var data=shuju.data;    // [{},{},{},......]
    121            
    122           $.each(data,function (i,weekend) {
    123               //console.log(weekend);  // {week: "周日", list: Array(19)}
    124               console.log(weekend.list);  // {week: "周日", list: Array(19)}
    125               var week= weekend.week;
    126               $("body").append("<div>"+week+"</div>");
    127 
    128               $.each(weekend.list,function (i,show) {
    129                   console.log(show); // {time: "1800", name: "《都市现场》90分钟直播版块", link: "http://www.jxntv.cn/live/jxtv2.shtml"}
    130 
    131                   var $a=$("<a>");  // <a></a>
    132                   $a.html(show.name);
    133                   $a.attr("href",show.link);
    134 
    135                   $("body").append('<p>');
    136                   $("body").append($a);
    137                   $("body").append('</p>');
    138 
    139               })
    140 
    141 
    142           })
    143 
    144     }
    145 </script>
    146 </body>
    147 </html>
    View Code

     注意 JSONP一定是GET请求

    CORS跨域资源共享(CORS,Cross-Origin Resource Sharing)

    其本质是设置响应头,使得浏览器允许跨域请求。

    项目一要访问项目二的视图,项目二的ajax请求代码如下

     1 <h1>项目2的首页cors</h1>
     2 
     3 <button class="send_ajax">send_ajax</button>
     4 
     5 <script>
     6 
     7     $(".send_ajax").click(function () {
     8 
     9         $.ajax({
    10             // 这里我访问s1的的send_ajax
    11             url:"http://127.0.0.1:8000/send_ajax/",
    12             type:'GET',  // head get post put delete
    13             success:function (data) {
    14                 console.log(data);
    15                 console.log('11')
    16             }
    17         })
    18 
    19     })
    20 </script>

    项目二通过路由找到视图返回数据的代码如下

     1 import json
     2 def send_ajax(request):
     3     # 授权的origin可以用*代替所有,methods可以多个,用逗号分开,简单的放一起,复杂放一起
     4     if request.method == "OPTIONS":  # 预检
     5         response = HttpResponse()
     6 
     7         response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
     8         response["Access-Control-Allow-Methods"] = "PUT"
     9 
    10         return response
    11 
    12     elif request.method == "PUT":   # 复杂请求,需要通过预检 put delete
    13         s = {"name": "egon", "age": 122}
    14 
    15         response = HttpResponse(json.dumps(s))
    16         response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
    17 
    18         return response
    19 
    20     elif request.method == 'GET':    # 简单强求 head get post
    21         s = {"name": "egon", "age": 122}
    22 
    23         response = HttpResponse(json.dumps(s))
    24         response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8011"
    25 
    26         return response

    流程:

    项目二向项目一发送请求,项目一根据请求匹配路由规则,找到视图,视图首先返回给浏览器,如果没有cors就会被浏览器拦截,有了cors设置,浏览器就不会拦截cors设置的请求方式,最终

    返回给项目一的数据,上述例子中,复杂请求(put,delete)先走预检,添加put请求,和允许访问的url,返回给浏览器,浏览器得到后在向服务器发送put请求,拿到数据,最后给项目一。

  • 相关阅读:
    学校的SQLServer的笔记
    Javaの集合学习
    XML的学习
    Java中学校没学过的东西
    MySQL的学习
    牛顿法及其收敛性
    c++编码规范
    C++标准库
    MATLAB编程技巧
    Matlab学习记录(函数)
  • 原文地址:https://www.cnblogs.com/jokerbj/p/8228988.html
Copyright © 2011-2022 走看看