CORS跨域问题与解决方案
CORS跨域问题
在前后端分离的项目中,前端向后端发送请求时,后端接收到了请求并且响应了,但是却被浏览器拦截(禁止)了,这就是CORS跨域问题。
同源策略
出现CORS是因为同源策略,它是浏览器的安全策略,浏览器不允许向不同的域发送请求获取数据。
- 同源(同一个域):IP地址和端口号一样。
比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据,这时浏览器上就会报错,这就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险。
CORS两种请求
浏览器还将跨域请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)
- 简单请求:只会向后端发送一次请求。
- 非简单请求:会向后端发送二次请求,第一次发送options请求,这是预检请求,如果允许,就会发送第二次真正的请求。
满足以下两个条件,就是简单请求:
- 请求方法是这三种方法之一:HEAD、GET、POST。
- HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个数据类型,application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求
服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’
非简单请求
由于非简单请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
与CORS类似的问题还有:
- xss跨站脚本攻击
- csrf跨站请求伪造
- cors跨域资源共享
解决方案
如果想要解决CORS(跨域资源共享),需要服务端在响应头中加入固定的东西,这样浏览器就能允许数据进入。
自己解决
因为需要在响应头中添加固定的东西,所以可以使用中间件:
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
def process_response(self, request, response):
# 判断是否是非简单请求,先发送options请求就是非简单请求
if request.method == "OPTIONS":
# *代表允许所有
response["Access-Control-Allow-Headers"] = "*"
# 允许的源写*代表允许所有
response["Access-Control-Allow-Origin"] = "*"
return response
别忘了在配置文件中添加自定义的中间件
第三方解决
1.安装模块:这个模块可以会更改你的django版本,安装完记得查看django版本是否被更改了。
pip install django-cors-headers
2.配置文件中添加app:
INSTALLED_APPS = [
...
'corsheaders',
]
3.配置文件中添加中间件:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware'
]
4.配置文件添加配置:
CORS_ORIGIN_ALLOW_ALL = True
# 允许的请求
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
# 允许请求头中的参数
CORS_ALLOW_HEADERS = (
'accept-encoding',
'authorization',
'content-type',
'origin',
'user-agent',
)
如果请求头中带了{'name':'tom'},就需要去配置文件中的CORS_ALLOW_HEADERS添加name参数:
CORS_ALLOW_HEADERS = (
...
'name',
)
或者一劳永逸,直接允许所有请求头带任何参数:
CORS_ALLOW_HEADERS = '*'