momo's Blog.

django前后端分离的一些问题及解决方案

字数统计: 770阅读时长: 3 min
2020/09/15 Share

前言

django 前后端分离时,会遇到很多问题,再次罗列一下,省的采坑.

解决跨域问题

前后端分离,首先解决的问题就是跨域问题.

我们需要安装用于解决跨域的插件

1
python -m pip install django-cors-headers

在setting 中添加如下配置

1
2
3
4
5
6
7
8
9
10
11
12
# 将corsheaders添加为我们的django app
INSTALLED_APPS += (
'corsheaders',
)

# 添加自定义中间件

注意中间件顺序, 跨域的中间件尽量放置在前
MIDDLEWARE += (
'corsheaders.middleware.CorsMiddleware',
"django.middleware.common.CommonMiddleware",
)

默认生产环境配置

1
2
3
4
5
6
# 白名单, 域名请按照前段实际配置修改
CORS_ORIGIN_WHITELIST = [
'http://localhost:8080',
]
# 允许跨域使用 cookie
CORS_ALLOW_CREDENTIALS = True

开发环境需要根据环境变量进行判断

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
#在本地开发环境下开启跨域允许
if ENVIRONMENT == 'dev':
# 跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = [
'http://localhost:8080',
]

CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)

CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)

解决 403 csrf token认证问题

Django为了防止CSRF攻击, 会在render的时候在页面中隐藏一个csrf_token。下次请求的时候需要带上这个token才能请求成功。

但是我们前后端分离的项目,根本用不到django自带的模板引擎,那我们怎么去拿到这个token呢?

实际上,在django应用中, csrftoken会额外存一份在我们应用的cookie中,所以我们只需要拿到cookie的token值每次带上他就行。

但是我们也知道,只有在同域名下我们才共享cookie的,所以我们需要保证在开发环境下,前后端域名需要保持一致。

随后,我们在vue中新建http.js

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
import axiox from 'axios'

const http = axiox.create({
baseURL: 'http://localhost:8001/'
})

function getCsrftokenByCookie() {
const cookie = document.cookie.split(';')
// 获取csrftoken
let csrftoken = ''
for (const i in cookie) {
if (cookie[i].indexOf('csrftoken') !== -1) {
csrftoken = cookie[i].split('=')[1]
}
}
return csrftoken
}

// 允许跨域发送请求时携带cookie
http.defaults.withCredentials = true
http.interceptors.request.use(config => {
config.headers.common['X-CSRFToken'] = getCsrftokenByCookie()
return config
})

export default http

随后在次刷新页面,哦豁!报错了!Invalid Host header

解决这个问题,我们只需要在前端项目目录下新建一个vue.config.js文件,并添加如下配置:

1
2
3
4
5
module.exports = {
devServer: {
disableHostCheck: true
}
}

在第一次请求中获取到csrf_token

前后端分离中,第一次POST请求并没有携带token,那么我们可以在页面第一次初始化的时候,将token请求过来

1
2
3
4
from django.middleware import csrf
def get_token(request):
token = csrf.get_token(request)
return JsonResponse({'token': token})

这样,前端发送get请求后,会自动在cookie中写入csrftoken

在Django类视图中使用 装饰器

在蓝鲸框架中
默认login_exempt只能装饰函数视图上,因为login_exempt是为函数准备的装饰器,所以类视图无法直接使用,需要使用method_decorator将其转换为适合类视图使用的装饰器。name=’dispatch’代表:为视图中的所有请求方法添加装饰器

1
2
3
4
5
6
from blueapps.account.decorators import login_exempt
from django.utils.decorators import method_decorator
@method_decorator(login_exempt, name='dispatch')
class Test(View):
def get(self, request, *args, **kargs):
return HttpResponse("aaa")
CATALOG
  1. 1. 前言
  2. 2. 解决跨域问题
  3. 3. 解决 403 csrf token认证问题
    1. 3.1. 在第一次请求中获取到csrf_token
  4. 4. 在Django类视图中使用 装饰器