CORS跨域问题与解决方案

CORS跨域问题

在前后端分离的项目中,前端向后端发送请求时,后端接收到了请求并且响应了,但是却被浏览器拦截(禁止)了,这就是CORS跨域问题。

image

同源策略

出现CORS是因为同源策略,它是浏览器的安全策略,浏览器不允许向不同的域发送请求获取数据。

  • 同源(同一个域):IP地址和端口号一样。

比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据,这时浏览器上就会报错,这就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险。

CORS两种请求

浏览器还将跨域请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)

  • 简单请求:只会向后端发送一次请求。
  • 非简单请求:会向后端发送二次请求,第一次发送options请求,这是预检请求,如果允许,就会发送第二次真正的请求。

满足以下两个条件,就是简单请求:

  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

简单请求

服务器设置响应头: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 = '*'
posted @ 2022-07-06 20:33  Yume_Minami  阅读(968)  评论(0编辑  收藏  举报