从Django后端处理跨域问题

前端报错欣赏:

1
Access to XMLHttpRequest at 'http://127.0.0.1:8000/todolist/getalltodo' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

场景:运行在localhost:5137的前端项目需要访问运行在localhost:8080的接口

原因:浏览器存在同源策略机制,即不允许脚本访问外部资源,只要域名、协议、端口其中一个不一致就会出现跨域问题。

特点

  1. 跨域问题是浏览器侧的限制,所发送的请求是正常的,只是浏览器不接受
  2. 只约束XmlHttpRequest,不约束imgiframescript等具有src属性的标签

解决:添加中间件、反向代理、jsonp或利用插件

插件

使用django-cors-headers插件。插件是最快的,功能也简单详细,有手就行,文档在这里:文档地址

文档也很简单明了,需要注意的是Python和Django的版本。

安装

1
python -m pip install django-cors-headers

添加应用

1
2
3
4
5
INSTALLED_APPS = [
...,
"corsheaders",
...,
]

添加中间件

1
2
3
4
5
6
7
MIDDLEWARE = [
...,
"corsheaders.middleware.CorsMiddleware",
# 这条是Django自带的,提醒上一条应该放在这条的上面
"django.middleware.common.CommonMiddleware",
...,
]

其他配置信息(在setting.py底部添加)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CORS_ALLOW_CREDENTIALS = True  # 跨域处理:允许携带cookie

CORS_ALLOWED_ORIGINS = [ #设置访问白名单
'http://localhost:5173',
'http://127.0.0.1:8000'
]

CORS_ALLOW_HEADERS = [ # 配置预检请求
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-requested-with",
]

添加中间件

导包

1
from django.utils.deprecation import MiddlewareMixin

定义中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CORSMiddleWare(MiddlewareMixin):
"""
设置跨域的中间件
"""

def process_response(self, request, response):
# 添加请求头
# 允许你的域名来获取数据(也可以指定域名)
response['Access-Control-Allow-Origin'] = '*'

if request.method == 'OPTIONS':
# 允许你携带Content-Type请求头,也可以设置别的自定义字段(不设置客户端设置的就不能通过预检)
response['Access-Control-Allow-Headers'] = 'Content-Type,k1, k2'

# 允许你发送DELETE,PUT的请求方式
response['Access-Control-Allow-Methods'] = 'DELETE,PUT'

# 允许设置缓存时间
response['Access-Control-Max-Age'] = 20

return response

注册

1
2
3
4
5
6
7
8
9
10
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middle.cors_middle_ware.CORSMiddleWare', # 自定义跨域中间件
]

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$('#btn').on('click', function () {
$.ajax({
url: 'http://localhost:9000/test1/',
method: 'post',
data: {
username: $('#name').val()
},
headers: {
'k1': 'hello'
},
success: function (data) {
console.log(data)
}
})
})

jsop

(跑题了,这里属于前端了)利用script标签的src属性(浏览器允许script标签跨域),利用js脚本动态的在头部引入跨域的地址

不足:只能是get请求,不能是post等别的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 方法一、动态的添加跨域地址
function Jsonp1(){
var tag = document.createElement('script');
tag.src = "http://c2.com:8000/test/";
document.head.appendChild(tag);
document.head.removeChild(tag);
}

function Jsonp2(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'GET',
dataType: 'JSONP',
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}

反向代理没有试过,不太清楚是怎么搞的,有朋友了解可以评论区交流~


从Django后端处理跨域问题
https://zhouyinglin.cn/post/48f8b261.html
作者
小周
发布于
2023年1月18日
更新于
2023年1月19日
许可协议