Django解决跨域请求:CORS原理、JsonP与中间件配置详解

七月
七月
发布时间:2026-10-13 | 6人浏览过
原创

本文详细解析Django中处理跨域请求的两种主要方式。首先介绍CORS(跨域资源共享)机制,区分简单请求与复杂请求(预检OPTIONS),并通过Django中间件配置响应头实现全类型跨域。其次回顾JsonP技术,利用script标签绕过同源策略仅支持GET请求。文章提供完整代码示例,涵盖视图、HTML及中间件注册步骤,帮助开发者理解并实施跨域解决方案。

Django跨域处理概述

前言

CORS(Cross Origin Resource Sharing,跨域资源共享)是浏览器端解决跨域问题的核心机制。

在CORS规范下,跨域请求被划分为简单请求和复杂请求两类,两者的处理流程有所不同。

CORS机制与请求分类

简单请求

要被视为简单请求,必须同时满足以下两个条件。

HTTP请求方法仅限于HEAD、GET或POST这三种之一。

请求头(Headers)中不得包含除以下字段之外的任何自定义字段:

Accept、Accept-Language、Content-Language、Last-Event-ID

此外,Content-Type请求头的值必须严格限定为以下三种类型之一:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

任何不满足上述条件的请求,均被归类为复杂请求。

对于复杂请求,浏览器会先自动发送一个预检请求(Preflight),即OPTIONS请求,以确认服务器是否允许该跨域操作。

浏览器同源策略解析

浏览器的同源策略

跨域访问受限的根本原因在于浏览器遵循的同源策略。

这意味着,浏览器默认会拦截非同源的资源请求。

所谓非同源,是指域名、协议或端口中任意一项与当前页面不一致的情况。

需要注意的是,浏览器仅限制表单提交和Ajax(XMLHttpRequest/Fetch)等脚本发起的跨域请求,而不会阻止通过src属性加载资源。

因此,CDN资源、图片等通过src属性引用的跨域加载行为是正常的。

JsonP跨域方案

JsonP实现跨域

JsonP(JSON with Padding)利用浏览器不限制src属性跨域的特性来实现数据交互。

由于script标签的特性,JsonP只能用于实现GET请求的跨域。

首先准备后端视图文件。


from django.http import HttpResponse
from rest_framework.views import APIView

class TestView(APIView):
  def get(self, request):
    return HttpResponse("handlerResponse('is ok')")
    # 注意返回的函数以及参数的格式

接着编写前端HTML文件。


<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <title>JsonP跨站请求测试</title>
</head>
<body>
<script>
  // 函数名应为handlerResponse,这是一种约定俗成
  function handlerResponse(data) {
    alert(data)
  }
</script>
<!--必须放在被执行函数的script标签的下面,否则会报错函数不存在-->
<script src="http://127.0.0.1:8000/test/"></script>
</body>
</html>

接下来进行实际测试。


从测试结果可以看出,我们成功实现了通过JsonP跨域获取数据。

然而,JsonP仅支持GET请求,且前后端交互逻辑较为繁琐,目前在实际项目中已较少使用。

Django中间件配置CORS

在Django中间件中添加响应头

通过配置Django中间件添加CORS响应头,可以同时支持简单请求和复杂请求的跨域访问。

第一步,准备中间件代码。


from django.utils.deprecation import MiddlewareMixin

class MyCors(MiddlewareMixin):
  def process_response(self, request, response):
    # 如下,等于'*'后,便可允许所有简单请求的跨域访问
    response['Access-Control-Allow-Origin'] = '*'

    # 判断是否为复杂请求
    if request.method == 'OPTIONS':
      response['Access-Control-Allow-Headers'] = 'Content-Type'
      response['Access-Control-Allow-Methods'] = 'PUT,PATCH,DELETE'

    return response

编写完成后,务必在Django配置文件中注册该中间件。

第二步,编写处理跨域请求的视图文件。


from django.http import HttpResponse
from rest_framework.views import APIView

class TestView(APIView):
  def get(self, request):
    return HttpResponse("这是GET请求的数据")
  def post(self, request):
    return HttpResponse("这是POST请求的数据")
  def put(self, request):
    return HttpResponse("这是PUT请求的数")

第三步,编写前端HTML测试文件。


<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <title>test</title>
</head>
<body>
<button id="sign">点击发送跨站请求</button>
<script>
  $('#sign').click(function () {
    $.ajax({
      url: 'http://127.0.0.1:8000/test/', // 要访问的外站
      type: 'put', // 请求类型, put为复杂请求
      contentType: 'application/json', // 指定为'application/json'后,将变为复杂请求
      success: function (data) {
        // 请求成功后将执行该函数
        // data是外站发送过来的数据
        alert(data)
      },
    });
  });
</script>
</body>
</html>

测试效果如下所示。


由此可见,我们成功实现了复杂请求的跨域,简单请求自然也能正常通过。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表