同源策略,跨域资源共享和JSONP

1. 同源策略

  同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

  一个源的定义:

    协议+域名+端口三者组合都相同,则属于同源策略,其他都是跨域策略

2. 跨域资源共享

        跨域资源共享(CORS)是一份浏览器技术的规范,提供了Web服务器从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是JSONP模式的现代版。与JSONP不同,CORS除了支持GET方法以外,还支持其他HTTP方法。用CORS可以让网页设计师用一般的 XMLHTTPRequest,这种方式的错误处理比JSONP要来的好。另一方面,JSONP可以在不支持CORS的老旧浏览器上运作,现代的浏览器都支持CORS。

      在django应用中,实现跨域操作有以下几种:

           1. 在表单提交中, 加上{% csrf_token %}。

           2. ajax提交时,在附加参数中添加 {'csrfmiddlewaretoken': ' {{crsf_token}} '}

           3.  安装django第三方包:https://github.com/OttoYiu/django-cors-headers

3. JSONP

        由于同源策略,一般来说不允许JavaScript跨域访问其他服务器的页面对象,但是HTML的<script>元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

       关于JSON和JSONP那点事: JSON是数据交换格式, JSONP是一种跨域的数据交换协议

  JSON的优点:

    1、基于纯文本,跨平台传递极其简单;

    2、Javascript原生支持,后台语言几乎全部支持;

    3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;

    4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;

    5、容易编写和解析,当然前提是你要知道数据结构;

       JSON的优点:(摘自:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html)

    1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

    2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);

    3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

    4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

    5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

    6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

    7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

               实现原理:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script); 
    </script>
</head>
<body>

</body>
</html>

  利用Jquery的JSONP请求: 实现一个简单的抽奖程序

       $(function(){
           var turning = false;
           $("#startbtn").click(function(){
                        if(!turning){
                turning = true;
                $.ajax({ 
                    type: 'GET', //Type即使写的是POST也是按照GET请求发送
                    url: "{% url 'mall:lottery' %}", 
                    // dataType: 'json', 
                    dataType: 'jsonp',
                    jsonp: 'callback',
                    jsonpCallback: 'lottery' ,
                    cache: false,
                    // data: {'csrfmiddlewaretoken': '{{csrf_token}}'},
                    success:function(json){ 
                        $("#startbtn").css("cursor","default"); 
                        var a = json.angle; //角度 
                        var p = json.prize; //奖项 
                        $("#startbtn").rotate({ 
                            duration:2000, //转动时间 
                            angle: 0, 
                            animateTo:1800+a, //转动角度 
                            easing: $.easing.easeOutSine, 
                            callback: function(){ 
                                alert('恭喜你,中得'+p+'!'); 
                                $("#startbtn").css("cursor","pointer"); 
                                turning = false;
                            } 
                        }); 
                    },
                    error: function(){ 
                        alert('出错了!'); 
                        return false; 
                    }, 
              }); 
          }
      });
    });                      

       Django后台: 

#@csrf_exempt
def lottery(request):
    prize_lst = {
        '一等奖': {'min': 1, 'max': 29, 'v':1},
        '二等奖': {'min': 302, 'max': 328, 'v':2},
        '三等奖': {'min': 242, 'max': 268, 'v':5},
        '四等奖': {'min': 281, 'max': 208, 'v':7},
        '五等奖': {'min': 122, 'max': 148, 'v':10},
        '六等奖': {'min': 62, 'max': 88, 'v':25},
        '七等奖': {'min': [32,92,152,212,272,332], 'max': [58,118,178,238,298,358], 'v':50},
    }
    result_dic = {}
    prize = get_rand_prize(prize_lst)
    angle_min = prize_lst[prize]['min']
    angle_max = prize_lst[prize]['max']
    if prize == '七等奖':
        angle_len = len(prize_lst[prize]['min'])
        i = randint(0,angle_len)
        result_dic['angle'] = randint(prize_lst[prize]['min'][i-1], prize_lst[prize]['max'][i-1])
    else:
        result_dic['angle'] = randint(prize_lst[prize]['min'], prize_lst[prize]['max'])
    result_dic['prize'] = prize
    func = request.GET.get('callback')
    content = f'{func}({result_dic})'
    return HttpResponse(content, content_type='application/javascript')
    # return JsonResponse(result_dic)

      ajax与jsonp之间的区别:

            1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

            2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

            3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

            4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

4. 跨域解决方案

    (1). 在服务器端启用CORS

    (2). 让无服务器端用于处理JSONP的能力

   这两种方法区别是什么?

      (1)  JSONP只支持GET请求, CORS则支持GET, POST, PUT, DELETE等标准方法

      (2)  使用JSONP时,服务器端处理客户请求的callback参数,而使用CORS则不需要

      (3) JSONP从服务器端获取的是script文件,而CORS获取是一段XML或者json或者其他格式文件

      (4) JSONP支持老实浏览器,而CORS只支持现代浏览器

原文地址:https://www.cnblogs.com/learning-skills/p/7607059.html