前言

   在前后端分离项目中,如何解决跨域请求是一个必须要面对的问题。因为前端和后端的数据交互会被浏览器的同源策略所挟持,在很早之前我在博客园发了一篇文章,大概就说了一下如何简单粗暴的解决跨域。

   其实那种解决办法是不适用于内部项目的,而是对一些公共的开发接口做访问进行数据获取,下面是文章链接:

   jQuery JSONP解决跨域请求

CORS

   CORS就是跨域资源共享的意思,它需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

   整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

   因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

基本流程

   浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。 浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

请求区别

   只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求。

  1. 请求方法是以下三种方法之一:

       HEAD GET POST

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

处理情况

   浏览器对于上面两种请求处理,会有不一样的方式:

   简单请求

   浏览器只会发送一次请求,然后后端将会返回数据,此时后端如果没有做跨域资源请求的允许,数据将会被浏览器同源策略所拦截。

   非简单请求

   浏览器会发送两次请求,第一次请求方式为OPTIONS,大概就是做一个预检查,检查后端是否允许第二次请求的发送。

   如果允许,才会发送第二次请求,后端会将第二次请求的数据返回,如果后端没有做跨域资源请求的允许,数据将会被浏览器同源策略所拦截。

   如果不允许,浏览器就不会发送第二次请求。

后端解决

   对于简单请求来说,我们只需要允许跨域资源共享即可。

   所以只需要在后端设置一个请求头:

Access-Control-Allow-Origin = "域名或者*"

   对于非简单请求来说,我们需要让预检进行通过,此外还需要允许跨域资源共享,所以需要设置最少设置两个或多个请求头:

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
# 这两个是让预检通过
Access-Control-Allow-Headers = "Content-Type"
Access-Control-Allow-Headers = "authorization" #JWT认证 # 下面这个是允许资源共享
Access-Control-Allow-Origin = "域名或者*"

基本总结

   一言以蔽之,当前端跨域向后端发送、请求数据时,有可能发简单请求,也有可能发非简单请求。

   简单请求只会发一次,而非简单请求会发两次请求。

   如果是简单请求,数据就会直接返回,如果是非简单请求,则需要后端做出一些相应的设置才会允许第二次真正请求的发送。

   对于非简单请求的预检来说,它其实是规定了前端能够去使用哪些请求方式,如GET/POST,同时还允许请求头中有什么,如Content-Type以及JWT随机字符串。

   我举个例子,如果前端要跨域通过POST请求发送一个JSON数据那么它的流程如下:

    1. 发送OPTIONS请求进行预检,检测是否允许带有Content-Type请求头(因为JSON格式必须由该请求头声明)
    2. 预检通过后,发送POST请求,Content-TypeJSON,带上数据发送过去。

Django解决

中间件

   对于Django来说,我们可以将处理设置在中间件中。不管你是使用drf还是原生Django,都可以这样设置,因为此时的request对象并未被包装。

   下面是同时支持简单请求和非简单请求的示例:

from django.utils.deprecation import MiddlewareMixin

class CorsMiddle(MiddlewareMixin):
def process_response(self, request, response):
response['Access-Control-Allow-Origin'] = '*' # 允许跨域,解决同源策略。简单和非简单请求都需要设置这个
if request.method == "OPTIONS":
# 可以加*,代表允许所有。 这里是预检的OPTIONS请求,它允许Content-Type请求头和authorization请求头。
response["Access-Control-Allow-Headers"] = "Content-Type" #
response["Access-Control-Allow-Headers"] = "authorization" return response # 记得在setting的中间件中配置

django-cors-headers

   这是一个模块,可以很好的解决同源策略问题,以及非简单请求的预检问题。

   下载安装即可:

pip install django-cors-headers

   然后需要进行注册:

INSTALLED_APPS = (
'corsheaders',
)

   添加中间件(其实它的解决方案和上面写的思路完全一模一样):

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware', # 写上面,因为Django中间件的返回顺序是自下而上。
...
]

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

CORS与Django的更多相关文章

  1. Django框架12 /同源、跨域、CORS

    Django框架12 /同源.跨域.CORS 目录 Django框架12 /同源.跨域.CORS 1. 同源策略 2. 跨域 3. 解决跨域:CORS/跨域资源共享 1. 同源策略 同源策略(Same ...

  2. python 全栈开发,Day100(restful 接口,DRF组件,DRF跨域(cors组件))

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确.方便快速开发 - 针对pc,手机,ipad,微信,支付宝... 使用同一个接口 2. 简述http协议? - 基 ...

  3. 1220 Vue与Django前后端的结合

    目录 vue的安装 Vue前端的设置 页面的分布 后台数据的替换 css样式 Django的配置 国际化配置 axios插件安装 CORS跨域问题(同源策略) 处理跨域问题: cors插件 axios ...

  4. 01-vue和api整合流程、CORS

    1.后端代码 1.项目结构 2.项目代码 主url from django.contrib import admin from django.urls import path, include url ...

  5. Django框架(二十九)—— 跨域问题

    目录 跨域问题 一.同源策略 二.CORS(跨域资源共享) 三.CORS两种请求(简单请求与非简单请求) 1.简单请求(一次请求) 2.非简单请求(两次请求) 四.CORS在Django中的应用 1. ...

  6. 异步请求之ajax

    一.初识ajax 1.下载引入jQuery <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"& ...

  7. 跨域AJAX

    本篇主要讨论JSONP和CORS这两种技术,使用它们的原因是为了完成对资源的跨域访问,也就是如何绕过浏览器的同源策略Same-origin Policy. 那么什么是Same-origin Polic ...

  8. 七、Ajax请求

    七.Ajax请求 客户端(浏览器)向服务端发起请求的形式: 地址栏:GET 超链接标签:GET form表单:GET或POST Ajax(重要):GET或POST或PUT或DELETE AJAX(As ...

  9. tornado django flask 跨域解决办法(cors)

    XMLHttpRequest cannot load http://www.baidu.com. No 'Access-Control-Allow-Origin' header is present ...

随机推荐

  1. C语言编程入门之--第六章C语言控制语句

    导读:本章带读者理解什么是控制语句,然后逐个讲解C语言常用的控制语句,含有控制语句的代码量多起来后就要注意写代码的风格了,本章末节都是练习题,大量的练习才能掌握好控制语句的使用. 6.1 什么是控制语 ...

  2. JavaScript事件对象属性e.target和this的区别

    前言: Event对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象eve ...

  3. ubuntu20 使用命令安装 redis

    安装 redis sudo apt-get install redis-server -y 配置文件 vi /etc/redis/redis.conf # 设置端口 port # 设置密码 requi ...

  4. devops-jenkins基于角色的权限管理RBAC

    一. devops-jenkins基于角色的权限管理RBAC 1 安装角色的rbac角色管理  1.1) 点击系统管理 1.2) 选择插件管理 1.3) 选择可选插件,输入role搜索 1.4) 选择 ...

  5. TiOps,支持容器,支持多云安全远程运维,疫情期间免费开放,助力远程办公

    TiOps,支持多云环境安全远程运维,疫情期间免费对外开放在疫情期间,为减少疾病传染可能性,许多公司的选择了在家远程办公.对于运维来说,既要远程运维,又要保证安全,还要在复杂的IT环境中保持高效,面临 ...

  6. linux centos 05

    centos7安装mariadb 1.yum  得配置yum源,配置阿里云的 两个 yum源  ,阿里云的yum源中,会有 mariadb的软件包 阿里云的yum仓库中,mariadb版本如下 mar ...

  7. 【UR #2】猪猪侠再战括号序列

    UOJ小清新题表 题目摘要 UOJ链接 有一个由 \(n\) 个左括号 "(" 和 \(n\) 个右括号 ")" 组成的序列.每次操作时可以选定两个数 \(l, ...

  8. linux学习(二)--setup.s

    执行过bootsect.s,加载了所有系统代码之后,开始向32位模式转变,为main函数的调用做准备,同样,附上图往下看 1 INITSEG = 0x9000 ! we move boot here ...

  9. 多路查找树(2-3 树、2-3-4 树、B 树、B+ 树)

    本文参考自<大话数据结构> 计算机中数据的存储 一般而言,我们都是在内存中处理数据,但假如我们要操作的数据集非常大,内存无法处理了,在这种情况下对数据的处理需要不断地从硬盘等存储设备中调入 ...

  10. Spark核心组件通识概览

    在说Spark之前,笔者在这里向对Spark感兴趣的小伙伴们建议,想要了解.学习.使用好Spark,Spark的官网是一个很好的工具,几乎能满足你大部分需求.同时,建议学习一下scala语言,主要基于 ...