🌈据说,看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。
前言:
🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
👍专栏介绍:个人记账分析系统 ,专门记录制作过程,每天进步一点点~
想看往期历史文章,可以浏览此博文: 历史文章目录,后续所有文章发布都会同步更新此博文~

Django 在前端发送 POST 请求的时候会带上 csrf_token ,但这是由模板自动渲染的,所以这里先尝试跨域使用模板。
一开始使用 vue.js ,默认端口 3000 ,如果使用 iframe 加载 Django 模板页面的话,就会触发跨域问题:

要解决这个问题找遍互联网,发现要在设置里加上:
X_FRAME_OPTIONS = 'ALLOW-FROM http://127.0.0.1:3000'
CSRF_TRUSTED_ORIGINS = ['127.0.0.1:3000']
CSRF_COOKIE_SAMESITE = None
CSRF_COOKIE_NAME = 'csrf'
此时页面能正常显示了,其中 X_FRAME_OPTIONS 选项的 ALLOW-FROM http://127.0.0.1:3000 属于过时语法,不会生效,但肯定不会被设置成默认的 DENY 属性,当然这里也不能设置他唯二有用的属性 SAMEORIGIN 因为这只是让同源可以加载在 iframe 里,我们这里端口不一样,不同源,你哪怕值为空也好。

但是这样处理后 cookie就只能限制于 iframe 里了,所以最终决定整个项目还是使用前后端完全分离的形式,单独获取 csrf_token。
还发现一个问题,Django 处理 csrf_token 的时候,本地域名必须是 127.0.0.1 ,而不能是 localhost ,换句话说,Django 处理的时候必须经过网卡( localhost 是不经过网卡的)。
给 Django 发送 POST 请求时候,Django 的返回:

简单点解决:
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def XXX(request):
if request.method == 'POST':
...
这样这个视图就临时不受 csrf 保护了,自然不会去验证 csrf_token 了,不过前后端分离使得我想直接应用在全部函数上,就直接把中间件去掉吧:
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',
]
在 settings.py 里注释掉 MIDDLEWARE 中注释掉 django.middleware.csrf.CsrfViewMiddleware 即可关闭 csrf 中间件了。
如果需要在启用 csrf 的情况下获取 csrf_token ,只需要新建一个获取的视图,使用如下方法:
import json
from django.shortcuts import HttpResponse
from django.middleware.csrf import get_token
def XXX(request):
return HttpResponse(json.dumps({'token': get_token(request)}), content_type="application/json,charset=utf-8")
不过跨域后 csrf_token 就基本失去了原来的防止 csrf 攻击的意义,所以干脆还是直接关闭。
刚才那些只是简单尝试发现可以,为了稳妥起见,前端后端各上一层保险方法:
django-cors-headers 扩展:pip install django-cors-headersapp :INSTALLED_APPS = ['corsheaders']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',
'corsheaders.middleware.CorsMiddleware' # 新添加的中间件
]
settings.py 文件中添加白名单:CORS_ORIGIN_WHITELIST = (
'http://127.0.0.1:3000',
'https://127.0.0.1:3000',
'http://localhost:3000',
'https://localhost:3000',
)
CORS_ALLOW_CREDENTIALS = True # 允许携带cookie
虽然是 vue 跨域,但实际上修改的是 vue 脚手架 vite 的配置,打开 vite.config.js 文件,里面粘贴如何代码:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
// 起个别名,在引用资源时,可以用‘@/资源路径’直接访问
resolve: {
alias: {
"@": resolve(__dirname, "src"),
},
},
plugins: [vue()],
// 配置前端服务地址和端口
server: {
host: '0.0.0.0',
port: 3000,
// 是否开启 https
https: false,
},
// 设置反向代理,跨域
proxy: {
'/api': {
// 后台地址
target: 'http://127.0.0.1:8000/api/',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
},
}
})
这样前端跨域代理就设置完成了。
据看到的资料表示,这反向代理是针对 axios 的,我暂时不用这个模块,所以也不实验验证是否成功了。
如果对跨域是否成功还不自信的话,可以添加以下代码让自己更安心一点,其中 * 可以改成自己的前端域名~
response = HttpResponse('')
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Credentials'] = 'true'
有一个深坑,就是 HBuilder X 启动的 vue 服务默认是 http://localhost:3000/ ,但这不经过网关!不经过网关就无法跨域设置 cookie !!!刚刚本博主就特别纳闷怎么回事,无意间将 localhost 改成 127.0.0.1 ,问题瞬间迎刃而解~