同源策略:JSONP和CORS

什么是同源策略:

  同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

  但是两个源在达成共识后,需要相互传递数据就需要避开这个问题。所有就要使用JSONP和CORS

  更多参考:点击

  Jquery中JSONP官方文档:点击

一、JSONP处理非同源拦截

基于Ajax的JSONP使用方法:一般情况下使用ajax提供的方法即可。

  传递数据方的地址:127.0.0.1:8000/jsonp

  传递数据方的视图函数:

def test_jsonp(request):
    new_dict = {
        ‘state‘: 1,
        ‘data‘: [0, 1, 2, 3]
    }

    func = request.GET.get(‘dingding‘) # 127.0.0.1:8000/jsonp/?dingding=回调函数名,如果接收数据方不指定jsonpCallback参数,回调函数默认为success

    return HttpResponse(‘{}("{}")‘ .format(func, new_dict))  # 需要把回调函数名和数据一起传过去,如果接收数据方不指定jsonpCallback参数,默认正常执行success

  接收数据方的地址:127.0.0.1:8005

  接收数据方的ajax:

    $(‘#jsonp‘).on(‘click‘, function () {
        $.ajax({
            url:‘http://127.0.0.1:8000/jsonp/‘,
            type:‘get‘,
            dataType:‘jsonp‘,  //指定接收jsonp格式
            jsonp:‘dingding‘,  // 即http://127.0.0.1:8000/jsonp/?dingding=回调函数名,默认为callback
            {#jsonpCallback:‘test‘, //指定回调函数为test,回调函数名为接收数据后需要执行的函数,默认执行success#}
            {#data:{"csrfmiddlewaretoken": $("[name = ‘csrfmiddlewaretoken‘]").val()}, //一定是get请求,不需要csrf#}
            success:function (data) {
                console.log(data)
            }
        })
        function test(data) {
            console.log(data)
        }
    })

  一个简单的jsonp发送和接收数据就已经完成,需要注意:

      1、Ajax提供简洁的方法,它的内部实现其实是函数的调用与DOM操作一个script标签

      2、使用Ajax提供的方法必须指定dataType参数为jsonp

      3、jsonp参数指定get请求发送的数据,例如http://127.0.0.1:8000/jsonp/?dingding=,默认为callback

      4、jsonpCallback指定回调函数名,不指定则默认执行success

jQuery中同样有专门的方法实现jsonp,但是不能指定回调函数:

  $("#jsonp").click(function () {
    $.getJSON("http://127.0.0.1:8000/jsonp/?callback=?", function (res) {
      console.log(res);
    })
  });

二、CORS彻底解决跨域:

  CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而解决AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。目前基本上主流的浏览器都支持CORS。所以只要后端服务支持CORS,就能够实现跨域。

  浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。一个请求需要同时满足以下两大条件才属于简单请求。

(1) 请求方法是以下三种方法之一:
    HEAD
    GET
    POST

(2)HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

  简单处理方式:

    在跨域场景下,当浏览器发送简单请求时,浏览器会自动在请求头中添加表明请求来源的 Origin 字段。

    我们的后端程序只需要在返回的响应头中加上 Access-Control-Allow-Origin 字段,并且把该字段的值设置为 跨域请求的来源地址或简单的设置为 * 就可以了。

    例如:我们可以在Django中间件中的process_response方法来给相应对象添加该字段。

from django.utils.deprecation import MiddlewareMixin

class CorsMiddleware(MiddlewareMixin):

    def process_response(self, request, response):
        # 给响应头加上 Access-Control-Allow-Origin 字段 并简单的设置为 *
        response[‘Access-Control-Allow-Origin‘] = ‘*‘
        return response

    添加中间件:必须放在最前面,因为要先解决跨域的问题。只有允许跨域请求,后续的中间件才会正常执行。

MIDDLEWARE = [
    ‘corsheaders.middleware.CorsMiddleware‘,  # 添加中间件
    ‘django.middleware.security.SecurityMiddleware‘,
    ‘django.contrib.sessions.middleware.SessionMiddleware‘,
    ‘django.middleware.common.CommonMiddleware‘,
    # ‘django.middleware.csrf.CsrfViewMiddleware‘,
    ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,
    ‘django.contrib.messages.middleware.MessageMiddleware‘,
    ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,
]

    中间件对所有视图有效,当需要为单独的一个视图添加时,只需在视图函数添加Access-Control-Allow-Origin字段即可

def index_jsonp(request):
    new_dict = {
        ‘state‘: 1,
        ‘data‘: [0, 1, 2, 3]
    }

    func = request.GET.get(‘callback‘)

    response = HttpResponse(‘{}({})‘ .format(func, json.dumps(new_dict)))
    response[‘Access-Control-Allow-Origin‘] = ‘*‘
    return response

  非简单的处理方式:

我们开发中常用到的那些请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json的都是非简单请求。

对于非简单请求,浏览器通常都会在请求之前发送一次 OPTIONS 预检 请求。该请求会像后端服务询问是否允许从当前源发送请求并且询问允许的 请求方法 和 请求头字段

举个例子:

我们前端使用axios向后端发送PUT请求,结果:

看看发送的具体请求:

解决办法也很简单,我们可以在后端简单的给响应对象添加上 常用请求方法(PUT、DELETE)的支持就可以了。

在上面Django的中间件中添加如下代码:

from django.utils.deprecation import MiddlewareMixin

class CorsMiddleware(MiddlewareMixin):

    def process_response(self, request, response):
        # 给响应头加上 Access-Control-Allow-Origin 字段 并简单的设置为 *
        response[‘Access-Control-Allow-Origin‘] = ‘*‘
        if request.method == ‘OPTIONS‘:
            # 允许发送 PUT 请求
            response[‘Access-Control-Allow-Methods‘] = ‘PUT, DELETE‘
            # 允许在请求头中携带 Content-type字段,从而支持发送json数据
            response[‘Access-Control-Allow-Headers‘] = ‘Content-type‘
        return response

三、使用django-cors-headers包

  我们这个中间件确实能解决目前的CORS跨域问题,但是我们的土方法肯定是不够严谨的,已经有人造好轮子-- django-cors-headers 了。

  我们只需要安装这个包,然后按需要配置一下就可以了。

  安装

pip install django-cors-headers

  注册APP

INSTALLED_APPS = [
    ...
    ‘app01.apps.App01Config‘,
    ‘corsheaders‘,  # 将 corsheaders 这个APP注册
]

  添加中间件

    必须放在最前面,因为要先解决跨域的问题。只有允许跨域请求,后续的中间件才会正常执行。

MIDDLEWARE = [
    ‘corsheaders.middleware.CorsMiddleware‘,  # 添加中间件
    ‘django.middleware.security.SecurityMiddleware‘,
    ‘django.contrib.sessions.middleware.SessionMiddleware‘,
    ‘django.middleware.common.CommonMiddleware‘,
    # ‘django.middleware.csrf.CsrfViewMiddleware‘,
    ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,
    ‘django.contrib.messages.middleware.MessageMiddleware‘,
    ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,
]

  配置

  你可以选择不限制跨域访问

CORS_ORIGIN_ALLOW_ALL = True

  或者你可以选择设置允许访问的白名单

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
    # ‘<YOUR_DOMAIN>[:PORT]‘,
    ‘127.0.0.1:8080‘
)

  更多详细配置详细请查看django-cors-headers项目    

原文地址:https://www.cnblogs.com/aizhinong/p/12424012.html

时间: 2024-11-11 11:07:14

同源策略:JSONP和CORS的相关文章

[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros

浏览器的同源策略: - 同源: 同方法,同域名,同端口 http://www.baidu.com:8000 http: 方法 www.baidu.com: 域名 8000: 端口 - 定义 网上解析非常好的一篇 http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html - 限制 ajax只能发给同源的网址: 限制原理: 浏览器request--->跨域服务器 浏览器阻止接收<----跨域服务器响应, 服务器已经做出响应了,而且

同源策略 JSONP(实践篇)

JSONP详解 json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是“用来跨域的”,一直不知道具体是个什么东西.今天总算搞明白了.下面一步步来搞清楚jsonp是个什么玩意. 同源策略 首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性.看起来不知道什么意思,实践一下就知道了. 1.随便建两个网页 一个端口是2698,一个2701,按照定义它们是不同源的. 2.用jQuery发起不同源的请求 在26

同源策略——浏览器安全卫士

对于软件开发人员来说,理解同源策略.能够非常好地攻克了一个痛点. 不同域名下的资源读写 ! 古代的楚河汉界明白地规定了两方的活动界限.假设没有这些界限,天下必将大乱.相同,在我们的浏览器,也有着一些界限和策略,才让 Web 世界之所以能如此美好地呈如今我们面前.这些安全策略有效地保障了用户计算机的本地安全与Web安全. 同源策略 浏览器有一个非常重要的概念--同源策略(Same-Origin Policy).所谓同源是指,域名,协议.port同样.不同源的client脚(javascript.A

同源策略——浏览器的安全卫士

对于软件开发者来说,理解同源策略,可以很好地解决了一个痛点, 不同域名下的资源读写 ! 古代的楚河汉界明确地规定了双方的活动界限,如果没有这些界限,天下必将大乱.同样,在我们的浏览器,也有着一些界限和策略,才让 Web 世界之所以能如此美好地呈现在我们面前,这些安全策略有效地保障了用户计算机的本地安全与Web安全. 同源策略 浏览器有一个很重要的概念--同源策略(Same-Origin Policy).所谓同源是指,域名,协议,端口相同.不同源的客户端脚(javascript.ActionScr

浏览器的同源策略与跨域处理

一.  同源策略 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 下表给出了相对http://store.company.com/dir/page.html同源检测的示例: 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互. 允许跨源访问的一些例子: <script src="..."></script> 标签嵌入跨域脚本.语法错误信息只能在同源脚本中捕捉到. <link rel="style

jsonp突破同源策略,实现跨域访问请求

跨域访问问题,相信大家都有遇到过.这是一个很棘手的问题.不过道高一尺,魔高一丈,对于这类问题,总有解决问题的方案.最近我又接触到了这个问题,解决的途径是ajax+jsonp. 说到这个问题,不得不说一下"同源策略(Same-Origin Policy)",它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源,就是必须协议.域名.端口都一致的,才叫做同源.例如:http://www.12306.cn和https://www.

Ajax跨域请求 同源策略与Jsonp

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现.同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个

同源策略与Jsonp

同源策略与Jsonp 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现. 同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个

浏览器的同源策略和CORS跨域

浏览器的同源策略和CORS跨域 什么是同源: 域名/ip + 端口 + 协议 http协议默认端口:80 https协议默认端口:443 浏览器对于非同源的请求会拒绝接受响应信息. 前后端分离的项目一般都会涉及到跨域问题 JSONP跨域(之前的解决方案) 不足: 只能GET请求 前端和后端都要支持 原理: 利用的就是浏览器对加载静态资源不做限制,比如 <script src="跨域的地址"></script> jQuery版JSONP $.getJSON(&qu