跨域
跨域是因为浏览器的同源策略导致的,也就是说浏览器会阻止非同源的请求。那什么是非同源呢?既域名不同,端口不同,都属于非同源的。比如我们用vue写了个前端页面,端口为8081,Django写了个后台,端口为8000,前端往后台提交数据,后台返回数据会被浏览器拦截,因为端口不同。这就是跨域。
浏览器只阻止表单以及ajax请求,并不会阻止src请求。所以我们得CDN,图片等src都可以发送。
跨域请求分为两种,一种是简单请求,一种是复杂请求。
简单请求
HTTP方法是下列方法之一
- HEAD、GET、POST
HTTP头信息不超过以下几种字段
- Accept,Accept-Language、Content-Language、Last-Event-ID
- Content-Type只能是下列类型中的一个
- application/x-www-from-urlencode
- multpart/from-data
- text/plain
复杂请求
任何一个不满足上述要求的情求,都认为是复杂请求
复杂请求会先发出一个预请求,我们也叫预检,OPTIONS请求
比如发送了一个post请求,Content-Type为application/json。就是复杂请求
解决跨域(方法一)
在很久很久以前,人们解决跨域是通过JSONP来实现的。jsonp的实现原理是根据浏览器不阻止src请求入手来实现的。
JSONP解决跨域只能发送get请求,并且实现起来需要前后端交互比较多,所以现在已经不使用了。
现在常用的解决跨域的方法是添加响应头,在response里添加响应头告诉浏览器不用对请求进行拦截。
因为跨域是浏览器的同源策略导致的,我们前端发送的数据是提交到后端的,后段也返回了数据,只是浏览器没有渲染。我们都知道Django的中间件会在视图之前和视图之后去执行,因为数据是返回了得,我们可以写个中间件,写个process_response方法,在返回响应之前执行,然后返回给浏览器就可以了
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"] = "DELETE, PUT, POST" return response
解决跨域(方法二)
使用第三方库解决跨域的问题
1.安装第三方库django-cors-headers
pip install django-cors-headers
2.django-cors-headers是一个app,所以需要我们在settings.py里的app里注册 corsheaders,尽量放在前面
3.添加中间件,需要放在 'django.middleware.common.CommonMiddleware' 中间件之前
'corsheaders.middleware.CorsMiddleware',
4.添加白名单
CORS_ALLOW_CREDENTIALS = True # 允许跨域时携带Cookie,默认为False CORS_ORIGIN_ALLOW_ALL = True # 所有ip都可以访问后端接口 # CORS_ORIGIN_WHITELIST = ["http://127.0.0.1:8080",["http://192.168.10.1:8080"] # 指定能够访问后端接口的ip或域名列表 # 允许访问的请求方法 CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) # 允许的headers CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', )
这样也可以解决跨域的问题,建议使用这种方法解决跨域