前后端分离django-restframework——解决跨域请求

news2024/12/23 8:34:10

为什么会出现跨域问题?
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

比如一个链接:http://www.baidu.com(端口默认是80端口),

如果再来一个链接是这样:http://api.baidu.com,这个就算是跨域了(因为域名不同)

再来一个:https://www.baidu.com,这个也是跨域了(因为协议不同,用的https)

再来一个http://www.baidu.com:8888,这个也算跨域,端口号不同

举个实际的例子:

  • API接口数据部署在baidu.com上;
  • Ajax文件部署在cnblogs.com上,Ajax文件会向API (baidu.com) 发送请求,返回数据;
  • 用户通过bing.com访问cnblogs.com的Ajax文件,请求数据

以上过程就发生了跨域访问。如果直接使用Ajax来请求就会失败,就像Chrome提示的:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

跨域直白点就是,请求协议,域名(IP),端口号,三个其中任何一个不同都算跨域

CORS

CORS(跨域资源共享,Cross-Origin Resource Sharing)是一种跨域访问的机制,可以让Ajax实现跨域访问 

那么如果跨域是什么样的呢?比如,我这里有个restframework项目作为服务器,项目名为drfversion,测试的app名叫testapp,url如下:

view:

启动项目,直接访问这个API接口测试:

在django的templates目录下新建一个test.html,简单的建立了一个vue和axios的项目,作为前端的异步请求,写入以下参数:

点那个谷歌浏览器图标,然后直接谷歌浏览器打开,这里这个功能是pycharm给我们提供的功能,此时这个作为客户端,访问:

里面的这个参数提示就是跨域了,浏览器默认有个同源策略,他检测到这个http://localhost:63342的url与我们后端启动的DRF项目url:http://127.0.0.1:8000/test/不同源,也就是跨域了,所以报错。

再看接口,看其实后端没有错误,已经给我们返回了数据:

所以跨域请求的根本原因是浏览器的同源策略造成的,要解决这个跨域请求就可以在这方面研究了

而跨域分简单请求和复杂请求

简单请求

HTTP方法是只能是HEAD, GET和POST

HTTP头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type

而且Content-Type只能是下列类型:

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

复杂请求

除了简单请求的都是复杂请求了,所以如果传输json数据,Content-Type类型就是json了,所以一定是复杂请求了

复杂请求会先发出一个预请求,又叫预检,OPTIONS请求

常见的解决跨域的方法

1.协议和域名,端口都是用同一个就行
2.利用jsonp解决跨域问题

 因为看代码相信你也看到了,那个script脚本标签导入的两个js文件,一个用的vue,一个用的axios,然后用到的是各自的cdn,url也都不一样:

其实也算跨域了,但是浏览器并没有给我们拦截,所以我们是否也可以直接用script的src属性来访问,当然可以:

刷新刚才那个前端客户端页面,发现真的可以这样

那么再大胆一点,发一个函数名怎么样?然后前端先定义好这个函数名,试试看:

后端的视图函数里返回这个函数调用的字符串:

前端访问,可行,确实打印了

但是,这只能做GET啊,如果做POST,PUT啥的请求呢?就没办法了,而且在调用函数时,前端和后端必须商量好函数名,必须统一才行,所以这jsonp还是有很大的弊端的

3.修改Django中的views.py文件


修改views.py中对应API的实现函数,允许其他域通过Ajax请求数据:

​def myview(_request):

    response = HttpResponse(json.dumps({"key": "value", "key2": "value"}))

    response["Access-Control-Allow-Origin"] = "*"

    response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"

    response["Access-Control-Max-Age"] = "1000"

    response["Access-Control-Allow-Headers"] = "*"

    return response

​

4.在后端做处理——Python是利用django中间件添加响应头 

GET:

现在什么都不做,只是get请求,再看下提示的是什么:

注意这句话:No 'Access-Control-Allow-Origin' header is present on the requested resource.

好,在后端写一个中间件:

配置文件里应用上:

重启项目,前端再次访问,这次终于没有红色的报错了

 

 POST:

再来个POST请求看看:

后端的view:

其他后端代码不变,前端访问,又变红了

注意这句话:Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

好的中间件做如下修改:

重启访问,有了:

OPTIONS(PUT,DELETE):

好如果是put或者delete请求呢?这个按前面说的简单请求与复杂请求的说法,这两个请求方式肯定是复杂请求了,即那个OPTIONS了,搞一个put的请求看看,还是先看看它报什么错:

view:

重启访问,报错提示的字段跟前面的POST请求字段好像是一个说法对吧

但是我们只加了post的,并没加put或者delete的,修改中间件:

重启访问,确实已解决

 然后,其实中间件还是稍微优化一下,把简单请求和复杂请求做个判断处理,复杂请求可以预检嘛,节省下资源:

重启访问,没有任何问题:

相关代码:

 中间件middle:

from django.utils.deprecation import MiddlewareMixin


class CorsMiddle(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,DELETE'
        return response

 

view:

from rest_framework.views import APIView
from rest_framework.views import Response
class TestView(APIView):
    def get(self, request):
        return Response('跨域测试')

    def post(self, request):
        return Response('post接口测试')

    def put(self,request):
        return Response('put请求测试')
   ....(还有个delete请求就省略了,跟put请求一样的)

settings:

MIDDLEWARE = [
    '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',
    'middle.CorsMiddle',
]

前端代码test.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
    //    function PrintTest() {
    //        console.log('jsonp test');
    //    }
    </script>

    <script src="http://127.0.0.1:8000/test/"></script>
</head>
<body>
<div id="app"></div>
<script>
    const app = new Vue({
        el: '#app',
        mounted() {
            axios.request({
                url: 'http://127.0.0.1:8000/test/',
                method: 'GET',// "POST","PUT","DELETE"
                //data:{
                //    "name":"jack",
                //}
            }).then(function (data) {
                console.log(data)
            })
        }
    })
</script>
</body>
</html>

以上4个方法,已经可以解决大部分的跨域请求问题,但是由于我后期再次遇到过更强大的问题:以上4个方法针对火狐浏览器没法,火狐浏览器安全性比较高,一样会报跨域请求,即使你在django的中间件添加了response处理

下面这个使用第三方库django-cors-headers的方法就可以完美解决火狐浏览器问题

5.使用第三方库django-cors-headers

在Django中,有人开发了CORS-header的middleware

只需在settings.py中做一些简单的配置即可,其他不用作任何修改,我们也不用自己手动的创建中间件对response处理了,直接用以下配置即可,  现在用起来服务器端完全开放,开启CORS,没有任何跨域烦恼 


安装django-cors-headers:

pip install django-cors-headers

  

在settings.py中增加:
INSTALLED_APPS = (



  ...



  'corsheaders',



  ...



)



...





MIDDLEWARE_CLASSES = (



  ...



  'corsheaders.middleware.CorsMiddleware',  # 注意顺序,必须放在Comon前面



  'django.middleware.common.CommonMiddleware',



  ...



)



#以下直接赋值放在settings.py里即可解决



CORS_ALLOW_CREDENTIALS = True



CORS_ORIGIN_ALLOW_ALL = True



CORS_ORIGIN_WHITELIST = ( '*' )



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',



)

总结:

  • 针对跨域请求,其实本质上是浏览器对返回的结果response的拦截
  • 最常见的解决办法就是在后端返回结果response时做数据处理,让浏览器不拦截

 

补充:

由于django的升级,如果你在安装的时候不指定版本的话,会默认安装最新版,且不指定django-cors-headers库版本,也会安装最新版,而以上内容是针对2.0的,所以,按照上面的配置的话,还是会报跨域请求错误,最根本的问题就是,一个协议的规则匹配

把上面的:

CORS_ORIGIN_WHITELIST = ( '*' )

换成以下的:

CORS_ORIGIN_WHITELIST = ('http://*.*.*:*', 'https://*.*.*:*')

其他不变,即可保证跨域请求正常,问题完美解决!!!

本次分享到此结束,感谢大家的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1888495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis 7.x 系列【16】持久化机制之 AOF

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 1. 概述 默认情况下&#xff0c;Redis 使用RDB持久化&#xff0c;但如果进程出现问题或电源中断…

企业如何在当前形势下实现精益生产?

近年来&#xff0c;企业面临诸多挑战&#xff0c;从成本控制到效率提升&#xff0c;每一项决策都关乎着企业的生死存亡。尤其是在全球经济一体化和市场竞争日益激烈的大背景下&#xff0c;企业如何实现精益生产&#xff0c;成为了摆在众多企业家面前的一道难题。今天&#xff0…

STM32 看门狗 HAL

由时钟图可以看出看门狗采用的是内部低速时钟&#xff0c;频率为40KHz 打开看门狗&#xff0c;采用32分频&#xff0c;计数1250。 结合设置的分频系数和重载计数值&#xff0c;我们可以计算出看门狗的定时时间&#xff1a; 32*1250/40kHz 1s 主函数中喂狗就行 HAL_IWDG_Ref…

ISP IC/FPGA设计-第一部分-SC130GS摄像头分析(0)

1.介绍 SC130GS是一款国产的Global shutter CMOS图像传感器&#xff0c;最高支持1280Hx1024V240fps的传输速率&#xff1b;SC130GS有黑白和彩色款&#xff0c;作为ISP开发选择彩色的&#xff0c;有效像素窗口为1288Hx1032V&#xff0c;支持复杂的片上操作&#xff0c;选择他理…

2023-2024华为ICT大赛中国区 实践赛网络赛道 全国总决赛 理论部分真题

Part1 数通模块(10题)&#xff1a; 1、如图所示&#xff0c;某园区部署了IPv6进行业务测试&#xff0c;该网络中有4台路由器&#xff0c;运行OSPFv3实现网络的互联互通&#xff0c;以下关于该OSPFv3网络产生的LSA的描述&#xff0c;错误的是哪一项?(单选题) A.R1的LSDB中将存在…

若依 ruoyi vue上传控件 el-upload上传文件 判断是否有文件 判断文件大小

console.info(this.$refs.upload.uploadFiles.length)//this.$refs.upload.uploadFiles.length 获取当前上传控件中已选择的文件大小//判断是否存在已上传文件 if(this.$refs.upload.uploadFiles.length 0){this.$modal.msgWarning("请上传文件");return; }

高质量免费数字人(整合包),是的,我又出手了~

在数字时代&#xff0c;我们不断追求更加逼真和高效的技术应用&#xff0c;特别是在数字人领域。腾讯推出了一款名为MuseTalk的革命性数字人产品&#xff0c;支持实时音频驱动的唇部同步数字人&#xff0c;迅速成为行业的新宠。&#xff08;先来一张美图镇楼&#xff09; Muse…

【SPIE独立出版】第四届智能交通系统与智慧城市国际学术会议(ITSSC 2024)

第四届智能交通系统与智慧城市国际学术会议&#xff08;ITSSC 2024&#xff09;将于2024年8月23-25日在中国西安举行。本次会议主要围绕智能交通、交通新能源、无人驾驶、智慧城市、智能家居、智能生活等研究领域展开讨论&#xff0c; 旨在为该研究领域的专家学者们提供一个分享…

鼠标点击器免费版?详细介绍鼠标连点器的如何使用

随着科技的发展&#xff0c;鼠标连点器逐渐成为了我们生活和工作中不可或缺的工具。它不仅能够帮助我们完成频繁且重复的点击任务&#xff0c;还能在很大程度上减少我们的手部疲劳&#xff0c;提高工作效率。本文将详细介绍鼠标连点器的使用方法&#xff0c;并推荐三款好用的免…

<软考>软件设计师-7数据库技术基础(总结)

(一) 数据库基本概念 1 数据库系统 数据:是数据库中存储的基本对象,是描述事物的符号记录。 数据的种类:文本、图形、图像、音频、视频、学生的档案记录、货物的运输情况等。 数据库DB:是长期存储在计算机内、有组织的、可共享的大量数据的集合。 数据库的基本特征: -1. 数据…

王者荣耀对折叠机进行专门适配优化,折叠机用户喜提加强

王者荣耀针对折叠屏手机做了针对性的适配优化&#xff0c;把折叠机的大屏幕优势发挥了出来——适配之后&#xff0c;用折叠屏玩王者荣耀拥有了更大的视野、以及更大的触控响应区域。 【更贴合折叠屏的视野适配】 此前王者荣耀并没有对折叠屏进行专门的适配&#xff0c;表现到…

基于YOLOv10深度学习的CT扫描图像肾结石智能检测系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

家用洗地机什么牌子好?四款公认品牌好的机型推荐

每个人都希望自己的家里面能够干干净净&#xff0c;就算不是一尘不染&#xff0c;也至少应该是整洁的&#xff0c;但是在这个快节奏的大环境下&#xff0c;做清洁对于人们来说&#xff0c;不是没时间&#xff0c;就是太累了。正当此时&#xff0c;一款造福懒人的神器——家用洗…

HarmonyOS APP应用开发项目- MCA助手(Day01持续更新中~)

简言&#xff1a; gitee地址&#xff1a;https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5 注&#xff1…

gif压缩工具免费在线哪个好?推荐4个实用压缩好物

压缩GIF动图相信不少朋友都会&#xff0c;但要想在压缩GIF的同时依旧最大限度地保持画质的清晰度&#xff0c;那可没那么简单&#xff01; 不过想要实现高清压缩&#xff0c;也还是有许多妙招可用的&#xff01;今天就给大家整理了4个我自用的压缩方法&#xff0c;保准能让gif…

WSL2安装ContOS7并更新gcc

目录 WSL2安装CentOS7下载安装包安装启动CentOS7 CentOS7更换国内源gcc从源码安装gcc卸载gcc CMake中使用gcc关于linux配置文件参考 WSL2安装CentOS7 Windows11官方WSL2已经支持Ubuntu、Open SUSE、Debian。但是没有centos&#xff0c;所以centos的安装方式略有不同。 下载安…

Pandas_DataFrame读写详解:案例解析(第24天)

系列文章目录 一、 读写文件数据 二、df查询数据操作 三、df增加列操作 四、df删除行列操作 五、df数据去重操作 六、df数据修改操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、 读写文…

强化学习-5 策略梯度、Actor-Critic 算法

文章目录 1 基于价值&#xff08; value-based \text{value-based} value-based &#xff09;算法的缺点2 策略梯度算法2.1 解释2.1.1 分母和分子相消2.1.2 对数函数的导数2.1.3 组合公式2.1.4 总结 3 REINFORCE算法4 策略梯度推导进阶4.1 平稳分布4.2 基于平稳分布的策略梯度…

LeetCode题练习与总结:二叉树的后序遍历--145

一、题目描述 给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[3,2,1]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a…

关于批量采集1688商品主图及链接的方式:软件采集/1688官方API接口数据采集

关于批量采集&#xff0c;我们通常用到的是软件 采集&#xff0c;或者通过1688官方API数据采集的形式&#xff1a;用户输入一组1688商品ID&#xff0c;一行一个&#xff0c;流程会自动逐个打开对应的1688商品详情页&#xff0c;采集主图的所有链接。 结果保存为表格的一行&…