Django 多方式实现跨域访问

article/2025/10/5 6:24:57

一、什么是跨域

1.1 跨越介绍

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。 这里说明一下,无法跨域是浏览器对于用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题了。
域可以理解为:协议 + 域名 + 端口号

  • 在前后端不分离的项目中,前端使用ajax发起请求时,前端发起请求的域与后端定义API的域一致,故不会存在跨域问题
  • 在前后端分离的项目中,前端使用ajax或者axios发起请求,前后端各自运行在自己的域下,所以在发起请求的时候就会造成跨域,比如前端使用脚手架创建,运行在http://127.0.0.1:8080 后端运行在http://127.0.0.1:8000 端口,当前端发起请求时,因为域(端口不一致)不同,就会造成跨域,浏览器便会阻止该请求。

1.2 跨域分类

跨域请求分为2种,一种是简单请求,一种是复杂请求。

  • 简单请求
只要同时满足以下两大条件,就属于简单请求
HTTP 方法是下列之一- HEAD- GET- POST HTTP 头信息不超出以下几种字段- Accept- Accept-Language- Content-Language- Last-Event-ID- Content-Type 只能是下列中的一个类型application/x-www-from-urlencodedmultipart/form-datatext/plain

任何一个不满足上述要求的请求,即会被认为是复杂请求
复杂请求会先发出一个预请求,我们也叫预检,OPTIONS请求

二、同源策略

浏览器只阻止表单以及ajax请求,并不会阻止src请求,所以我们的cdn,图片等src请求都可以发~~

2.1 Ajax测试

当我们向后端发起GET请求时,后端没有做跨域访问。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script><title>跨域请求测试</title>
</head><body><div id="app"><button  @click="Send">发送请求</button></div>
</body>
<script>new Vue({el:"#app",methods:{Send(){axios.get('http://127.0.0.1:8000/api/test/').then(function (response) {// 处理成功情况console.log(response);}).catch(function (error) {// 处理错误情况console.log(error);})}}})
</script>
</html>

浏览器给出提示。从origin 'null’访问’http://127.0.0.1:8000/api/test/'的XMLHttpRequest已经被CORS[跨域资源共享]策略阻止:没有’Access- control - allow - origin '头在请求的资源上存在。
在这里插入图片描述
我们在后端也发现,请求已经进来了,并成功返回了。所以数据被浏览器给劫持了
在这里插入图片描述

2.2 src 测试

当我们使用img script 标签的src来发起一个GET请求,会触发CORB(Cross-Origin Read Blocking )跨域读取阻塞。
当跨域请求回来的数据 MIME type 同跨域标签应有的 MIME 类型不匹配时,浏览器会启动 CORB 保护数据不被泄漏,被保护的数据类型只有 html xmljson。很明显 <script> <img> 等跨域标签应有的 MIME type htmlxmljson 不一样。
在这里插入图片描述

详情可以看这篇文章 https://juejin.cn/post/6844903831373889550

三,解决跨域访问

3.1 请求方式添加Headers来解决跨域问题

3.1.1 简单请求处理----以GET请求为例

在前面的测试时,我们发现请求已经到达,响应后被浏览器拦截了,所以需要我们告诉浏览器不要拦截
我这里使用的是django作为Web后端开发框架,当我们发起GET请求时,我们在后端添加浏览器所需要对应的请求体参数Access-Control-Allow-Origin

1.在TestView视图函数添加请求参数

def TestView(request):data = {"user": "jack","pwd": "123",}if request.method == 'GET':return HttpResponse(json.dumps(data),content_type='application/json')

4.重新启动,在此进行测试
前端代码如上,测试成功
在这里插入图片描述
注意:在进行post测试时,为了方便,我们需要注释掉django的csrf中间件,这是django自带的防止跨域请求伪造。
增加一个post方法判断

def TestView(request):data = {"user": "jack","pwd": "123",}if request.method == 'GET':		# 请求方法需要全部大写return HttpResponse(json.dumps(data),content_type='application/json')if request.method == 'POST':return HttpResponse(json.dumps(data),content_type='application/json')
# settings.py django的配置文件下
MIDDLEWARE = [......'django.middleware.common.CommonMiddleware',# 'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware',......
]

详细了解csrf:https://juejin.cn/post/6844903653757698062.

3.1.2 复杂请求处理

复杂请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json

复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"(OPTIONS)请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

PUT方法测试

  1. 修改前端代码 method: 'put'发送一个put请求过去。
    当发送put请求时,先送过来的是一个options请求,浏览器数据请求失败了,我们需要先在options请求的headers中添加Access-Control-Allow-Origin
    在这里插入图片描述
  2. 后端增加一个options判断,并添加Access-Control-Allow-Origin
# 在原来的视图函数中增加if request.method == 'OPTIONS':return HttpResponse(headers={"Access-Control-Allow-Origin":"*"})if request.method == 'PUT':return HttpResponse(json.dumps(data))
  1. 此时浏览器返回没有Access-Control-Allow-Methods ,表示PUT方法不被允许。我们在PUT和OPTIONS的headers中都再添加一个Access-Control-Allow-Methods ,然后前端继续发送PUT
    在这里插入图片描述
  2. 添加了Access-Control-Allow-Methods
    if request.method == 'OPTIONS':return HttpResponse(headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT"})if request.method == 'PUT':return HttpResponse(json.dumps(data),headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT"})
  1. 前端数据获取成功了
    在这里插入图片描述

JSON数据测试
前端携带一个json数据,向后端发送post请求,因为Content-Type中不包含JSON格式的数据,所以该请求为复杂请求
6. 前端携带JSON数据

Send(){axios({method: 'post',url: 'http://127.0.0.1:8000/api/test/',data:{"course_id":1,"course_title":"中华上下五千年深度解说"}}).then(response => {console.log(response)});
}
  1. 后端接收
def TestView(request):data = {"user": "jack","pwd": "123",}print(request.method)if request.method == 'GET':return HttpResponse(json.dumps(data))if request.method == 'POST':return HttpResponse(json.dumps(data))if request.method == 'OPTIONS':return HttpResponse(headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT"})if request.method == 'PUT':return HttpResponse(json.dumps(data),headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT"})return HttpResponse("okokok")
  1. 此时,浏览器提示我们需要添加Access-Control-Allow-Headers
    在这里插入图片描述
  2. 我们在POST和OPTIONS中都添加上去,浏览器数据接收成功了
if request.method == 'POST':return HttpResponse(json.dumps(data),headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT","Access-Control-Allow-Headers":"content-type"})
if request.method == 'OPTIONS':return HttpResponse(headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"PUT","Access-Control-Allow-Headers":"content-type"})

在这里插入图片描述

3.2 定义中间件来处理跨域问题

在上述的函数中,通过定义headers来处理跨域的多种情况,过于繁琐。我们可以写一个中间件来统一处理跨域问题
1.创建CorsMiddleware.py

from django.utils.deprecation import MiddlewareMixinclass CorsMiddleware(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"] = "DELETE, PUT, POST"return response

2.在Settings.py 配置文件的中间件中添加

MIDDLEWARE = [......'django.middleware.clickjacking.XFrameOptionsMiddleware','GOMusicApi.utils.cors_middleware.CorsMiddleware',
]

3. 重新书写视图,去掉所有的headers,重启项目

# 这里使用了rest_framework 
from django.http import JsonResponse,HttpResponse
from rest_framework.views import APIView
class TestView(APIView):def post(self,request):print(request.body.decode('utf-8'))data = {"user": "jack","password": "12333",}return JsonResponse(data,safe=False)# 这里是使用了def 函数来实现返回数据
def TestView(request):print(request.method)if request.method == 'POST':print(request.body.decode('utf-8'))data = {"user": "jack","password": "12333",}return JsonResponse(data,safe=False)return JsonResponse(data,safe=False)	# 这里return,因为先发送了options请求,故需要一个返回,不然后端会报没有返回对象的错误。

在这里插入图片描述

3.3 使用Django-cors-Headers 来处理跨域问题

1. 安装

pip install django-cors-headers

2. 在settings文件中进行配置

INSTALLED_APPS = [......'django.contrib.staticfiles','corsheaders',
]MIDDLEWARE_CLASSES = [.....'corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware',......
]

3. Django-cors-Headers 配置介绍
在 Django 设置中配置中间件的行为。您必须至少设置以下三个设置之一

CORS_ALLOWED_ORIGINS	# 默认为空列表,设置允许发送http请求的域名
CORS_ALLOWED_ORIGIN_REGEXES	# 允许域名列表使用正则模式
CORS_ALLOW_ALL_ORIGINS		# 运行所有的域名访问
  • CORS_ALLOWED_ORIGINS

    CORS_ALLOWED_ORIGINS  =  [ "https://example.com" , "https://sub.example.com" , "http://localhost:8080" , "http://127.0.0.1:9000" , 
    ]
    

以前此设置称为CORS_ORIGIN_WHITELIST,它仍然作为别名使用,新名称优先 【注意是django3.2使用新名称】

  • CORS_ALLOWED_ORIGIN_REGEXES
    一个字符串列表,表示与授权进行跨站点 HTTP 请求的 Origin 匹配的正则表达式。默认为[]。当 CORS_ALLOWED_ORIGINS不切实际时很有用,例如当您有大量子域时。

    CORS_ALLOWED_ORIGIN_REGEXES  =  [ r "^https://\w+\.example\.com$" , 
    ]
    

以前此设置称为CORS_ORIGIN_REGEX_WHITELIST,它仍然作为别名使用,新名称优先。【注意是django3.2使用新名称】

  • CORS_ALLOW_ALL_ORIGINS
    如果True,将允许所有来源。其他限制允许来源的设置将被忽略。默认为False。
    将此设置为True可能很危险,因为它允许任何网站向您的网站发出跨域请求。通常,您需要使用CORS_ALLOWED_ORIGINSCORS_ALLOWED_ORIGIN_REGEXES限制允许的来源列表。

以前此设置称为CORS_ORIGIN_ALLOW_ALL,它仍然作为别名使用,新名称优先。【注意是django3.2使用新名称】

这下面都是一些可选设置了,代码块中为默认值,一般默认值足够了

  • CORS_ALLOW_METHODS
    实际请求允许的 HTTP 动词列表

    CORS_ALLOW_METHODS  =  [ "DELETE" , "GET" , "OPTIONS" , "PATCH" , "POST" , "PUT" , 
    ]
    
  • CORS_ALLOW_HEADERS
    发出实际请求时可以使用的非标准 HTTP 标头列表。

    CORS_ALLOW_HEADERS  =  [ "accept" , "accept-encoding" , "authorization" , "content-type" , "dnt" , "origin" , "user-agent" , "x-csrftoken" , "x-requested-with" , 
    ]
    
    • CORS_ALLOW_CREDENTIALS
      如果为True,cookie 将被允许包含在跨站点 HTTP 请求中。默认为False。

注意:在 Django 2.1 中添加了SESSION_COOKIE_SAMESITE设置,默认设置为 “Lax”,这将阻止 Django 的会话 cookie 跨域发送。将其更改为无以绕过此安全限制。

详情链接:https://pypi.org/project/django-cors-headers/

4. 我的配置

# --------------------------------------- 跨域请求配置 cors ---------------------------------------#
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie
# CORS_ORIGIN_ALLOW_ALL = True   # 允许所有源访问
CORS_ORIGIN_WHITELIST = (       #设置白名单       CORS_ALLOWED_ORIGINS【django3.2】'http://127.0.0.1:8000','http://localhost:8000','http://192.168.1.107:8080'
)CORS_ALLOW_METHODS = (      #允许的方法'DELETE','GET','OPTIONS','PATCH','POST','PUT','VIEW',
)CORS_ALLOW_HEADERS = (      #允许的请求头'XMLHttpRequest','X_FILENAME','accept-encoding','authorization','content-type','dnt','origin','user-agent','x-csrftoken','x-requested-with','Pragma',
)

配置成功后,前端可以成功访问后端。

3.4 总结

浏览器对不同域之间做出的行为,对应不同的请求(简单请求和复杂请求)做出了不同的拦截方式,也就解释了为什么要添加请求参数。
Access-Control-Allow-Origin :为了解决域不一致的问题;
Access-Control-Allow-Methods :为了解决PUT,DELETE等方法
Access-Control-Allow-Headers:为了解决JSON数据传输的问题


http://chatgpt.dhexx.cn/article/JQlJEtWi.shtml

相关文章

Flask中跨域访问的实现

在我们访问不同的服务器时&#xff0c;就会涉及到了跨域的问题。因为不同域名之间是无法进行交流的&#xff0c;然后跨域就打破了这种规则的限制。说起Flask中的跨域&#xff0c;就不得不提到CORS组件了&#xff0c;相信大家在其它框架中也见过了它的身影。下面我们就跨域问题和…

Tomcat设置允许跨域访问

开发React项目时前端通过axios向后端代码发起请求调试的时候由于后端代码运行在8080端口而React项目运行在3000端口导致浏览器的同源策略禁止跨域请求&#xff0c;因此需修改Tomcat配置文件web.xml以开放跨域访问。 在tomcat的web.xml文件末尾加上&#xff1a; <filter>…

express 允许跨域访问

设置Express const express require(express) const bodyParser require(body-parser)const app express() // 处理参数 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));// 设置允许跨域访问该服务 app.all(*, function (req, res, nex…

tomcat 设置允许跨域访问

既然想到使用tomcat进行跨域的设置&#xff0c;而不使用在项目中设置header来解决&#xff0c;说明你也是tomcat 下的资源需要做跨域处理吧&#xff1f;这也是一个统一的允许跨域设置&#xff0c;tomcat下的所有请求都将放开&#xff0c;请注意。 具体步骤&#xff1a; 1.首先…

Chrome浏览器 设置跨域访问

由于浏览器的安全策略&#xff0c;不同域名的访问会被限制&#xff0c;导致不能访问 chorme或者360都可以使用下列设置来解决这个问题&#xff1a; &#xff08;1&#xff09;在电脑上新建一个目录&#xff0c;例如&#xff1a;C:\MyChromeEnvUserData &#xff08;2&#x…

tomcat9配置允许跨域访问

目录 一、问题描述二、解决办法三、程序截图 一、问题描述 最近在用Tomcat9最新版本部署程序的时候&#xff0c;发现其他服务访问我的静态资源的时候出现了跨域访问&#xff0c;结果很明显被拦截了&#xff0c;之前的文章介绍了Tomcat8.5的跨域配置&#xff0c;但是研究发现&a…

html的页面怎样直接跨域访问,【HTML】iframe跨域访问问题

概述 本地同一浏览器访问本地HTML文件和访问服务器端HTML文件,本地Iframe没有自适应高度,而服务器端的Ifrane自适应了高度。 1.问题重现: Chrome 版本 41.0.2272.101 (64-bit) OS:Win8.1 Chrome访问服务器端HTML文件呈现的结果 Chrome访问本地HTML文件呈现的结果 本地访问的…

vue跨域访问

vue跨域访问的问题&#xff08;基于允许跨域访问的前提&#xff09; 找到“ vue.config.js"&#xff0c;有些不是vue.config.js命名&#xff0c;也就是找到重写路径的js文件。重写一下自己要替换的路径&#xff0c;在原有基础上加一个 新建一个dev.js文件内容如下&#…

关于跨域访问

1 概念 2 案例 3 解决 4 实现 5 什么是跨域问题 示意图 1 概念 跨域访问&#xff0c;是指从一个域名的网页去请求另一个域名的资源。比如从 www.baidu.com 页面去请求 ww w.google.com 的资源。 但是一般情况下不能这么做跨域访问&#xff0c;因为有浏览器的 “ 同源策略…

什么是跨域?如何实现跨域访问?

跨域是指不同域名之间相互访问。 JavaScript同源策略的限制&#xff0c;A域名下的JavaScript无法操作B或是C域名下的对象 实现&#xff1a; 1、JSONP跨域&#xff1a;利用script脚本允许引用不同域下的js实现的&#xff0c;将回调方法带入服务器&#xff0c;返回结果时回调 2、…

跨域访问

跨域访问是什么 同源策略 1995年&#xff0c;同源政策由Netscape公司引人浏览器。目前&#xff0c;所有刘览器都实行这个政策。同源政策的目的&#xff0c;是为了保证用户信息的安全&#xff0c;防止恶意的网站窃取数据。随着互联网的发展&#xff0c;“同源政策”越来越严格…

朴素贝叶斯分类器python_python实现高斯朴素贝叶斯分类器

在这篇文章中,我们将使用我最喜欢的机器学习库scikit-learn在Python中实现朴素贝叶斯分类器。接下来,我们将使用经过训练的朴素贝叶斯(监督分类法)模型来预测人口收入。 在朴素贝叶斯分类器的文章中我们讨论了贝叶斯定理,我们希望你对贝叶斯定理的基础知识有一定的了解,如果…

贝叶斯分类器(matlab)

目标 下表由雇员数据库的训练数据组成。数据已泛化。例如&#xff0c;age“3135”表示年龄在31~35之间。对于给定的行&#xff0c;count表示department、status、age和salary在该行具有给定值的元组数。 DepartmentStatusAgeSalaryCountSalesSenior31-3546K-50K30Salesjunior…

Python实现朴素贝叶斯分类器

朴素贝叶斯分类器 文章目录 朴素贝叶斯分类器一、贝叶斯分类器是什么&#xff1f;贝叶斯判定准则朴素贝叶斯分类器举个栗子 二、相关代码1.数据处理2.生成朴素贝叶斯表&#xff08;字典&#xff09;关于如何判断属性的连续或离散性 根据朴素贝叶斯表计算预测标签 总结 一、贝叶…

贝叶斯分类器 (下)

目录 错误率与风险 朴素贝叶斯分类器 平滑&#xff1a;拉普拉斯修正 半朴素贝叶斯分类器 错误率与风险 书接上回&#xff0c;我们讲到最大后验概率&#xff0c;我们期望把概率最大时对应的属性&#xff0c;当做它最终的结果。我们自然也会思考&#xff0c;这样做准不准&…

贝叶斯分类器算法原理

目录 1.1&#xff0c;什么是朴素贝叶斯 1.2&#xff0c;极大似然估计 1.3&#xff0c;朴素贝叶斯分类器 1.4&#xff0c;朴素贝叶斯算法就程 1.5&#xff0c;朴素贝叶斯的优缺点 1.1&#xff0c;什么是朴素贝叶斯 在所有的机器学习分类算法中&#xff0c;朴素贝叶斯和其他…

【贝叶斯分类3】半朴素贝叶斯分类器

文章目录 1. 朴素贝叶斯分类器知识回顾1.1 类别&#xff0c;特征1.2 风险&#xff0c;概率1.3 类条件概率 2. 半朴素贝叶斯分类器学习笔记2.1 引言2.2 知识卡片2.3 半朴素贝叶斯分类器2.4 独依赖估计2.4.1 简介2.4.2 SPODE(超父独依赖估计)2.4.3 AODE(平均独依赖估计)2.4.4 TAN…

【贝叶斯分类2】朴素贝叶斯分类器

文章目录 1. 贝叶斯决策论回顾1.1 分类原理1.2 贝叶斯分类器1.3 P(c|x)1.4 计算公式1.5 极大似然估计 2. 朴素贝叶斯分类器学习笔记2.1 引言2.2 知识卡片2.3 朴素贝叶斯分类器2.4 拉普拉斯平滑 3. 朴素贝叶斯分类器拓展3.1 数据处理3.2 收集其他资料 1. 贝叶斯决策论回顾 1.1 …

朴素贝叶斯分类器

前知识了解&#xff1a; 贝叶斯决策论是概率框架下实施决策的基本方法。 贝叶斯定理&#xff1a; 贝叶斯定理是由果溯因的思想&#xff0c;当知道某件事情的结果后&#xff0c;由结果推断出这件事是由各种原因导致的概率为多少。极大似然估计&#xff1a; 朴素贝叶斯分类器…

贝叶斯分类器matlab实现

用matlab模拟最小错误率贝叶斯分类器与最小风险分类器&#xff0c;效果个人感觉还算能看的下去^_^ 注意&#xff1a;如果对实验原理还不算太懂&#xff0c;可以看其他大牛的博客或者看书&#xff0c;不管怎么样概率论知识是前提&#xff0c;不如乘法定理&#xff0c;条件概率&…