从Django后端处理跨域问题


前端报错欣赏:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
2
3
python -m pip 
install
django-cors-headers

添加应用

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

添加中间件

1
2
3
4
5
6
7
8
9
10
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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
2
3
4
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
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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'
] =
return
response

注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$(
'#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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 方法一、动态的添加跨域地址
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.top/2023/01/18/从Django后端处理跨域问题/
作者
小周
发布于
2023年1月18日
许可协议