前后端分离-跨域问题详解
一、跨域问题详解
什么是跨域问题:
跨域问题只会出现在前后端分离项目中,在前后端分离项目中,前端发送ajax请求到后端会跨域问题拦截,导致这个问题的原因是“同源策略”
什么是同源策略:
前端请求的url地址必须与浏览器上的url地址处于相同域上,也就是域名、端口、协议相同
-发送ajax请求的地址,必须跟浏览器上的url地址处于同域上
# 域 [域名,地址,端口,协议]
-请求成功,数据库返回,但是浏览器拦截
# 补充:浏览器中输入域名,没有加端口
-www.baidu.com---->dns--->解析成地址 192.168.2.3----》没有加端口,默认是80
-dns解析,先找本地的host文件
-可以修改本地的host做映射
解决同源策略的方式:
- 方式一:CORS 后端代码控制(本次所讲解)
- 方式二:Nginx反向代理 (常用)
- 方式三:搭建Node代理服务器
- 方式四:JSONP 很老,不会用了,只能发get请求
1、CORS解决跨域问题
简介:
cors(跨域资源共享),第三方模块,后端技术,通过在响应头中加入固定的头,来解决跨域问题
cors基本流程:
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
- 简单请求:
- 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
- 非简单请求:
- 浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错
什么是简单请求和非简单请求:
符合以下条件的请求就是简单请求,反之就是非简单请求
(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
# 演示简单和非简单请求
-如果是简单,直接发送真正的请求
-如果是非简单,先发送options,如果允许,再发真正的请求
cors解决跨域问题:
# 第一步:安装
pip install django-cors-headers
# 第二步:配置app
INSTALLED_APPS = [
'corsheaders'
]
# 第三步:配置中间件
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
# 第四步:在配置文件配置
# 允许所有域
CORS_ORIGIN_ALLOW_ALL = True
# 允许的请求方式
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',
'token',
)
2、自己编写代码解决跨域问题
思路:
- 当请求进入django时,拦截请求进行判断
- 如果是简单请求直接在响应头中加入"Access-Control-Allow-Origin"
- 指是否允许该域名访问
- 如果是非简请求,在响应头中加入"Access-Control-Allow-Headers"
- 指是否允许在响应头中添加的字段
- 将编写的代码注册成中间件,这样就不会出现跨域问题
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
def process_response(self,request,response):
if request.method=="OPTIONS": # 解决非简单请求的请求头
#可以加*
response["Access-Control-Allow-Headers"]="*"
# 允许前端的地址,所有请求头允许
response["Access-Control-Allow-Origin"] = "*"
return response