前言
django 前后端分离时,会遇到很多问题,再次罗列一下,省的采坑.
解决跨域问题
前后端分离,首先解决的问题就是跨域问题.
我们需要安装用于解决跨域的插件
1
| python -m pip install django-cors-headers
|
在setting 中添加如下配置
1 2 3 4 5 6 7 8 9 10 11 12
| INSTALLED_APPS += ( 'corsheaders', )
注意中间件顺序, 跨域的中间件尽量放置在前 MIDDLEWARE += ( 'corsheaders.middleware.CorsMiddleware', "django.middleware.common.CommonMiddleware", )
|
默认生产环境配置
1 2 3 4 5 6
| CORS_ORIGIN_WHITELIST = [ 'http://localhost:8080', ]
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(';') let csrftoken = '' for (const i in cookie) { if (cookie[i].indexOf('csrftoken') !== -1) { csrftoken = cookie[i].split('=')[1] } } return csrftoken }
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")
|