• 【毕业设计】前后端分离——解决cookies跨域


    🌈据说,看我文章时 关注、点赞、收藏帅哥美女们 心情都会不自觉的好起来。

    前言:
    🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
    ✨个人主页:点我直达,在这里肯定能找到你想要的~
    👍专栏介绍:个人记账分析系统 ,专门记录制作过程,每天进步一点点~

    想看往期历史文章,可以浏览此博文: 历史文章目录,后续所有文章发布都会同步更新此博文~

    人生苦短,我用python

    跨域问题

    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'
    
    • 1
    • 2
    • 3
    • 4

    此时页面能正常显示了,其中 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':
            ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样这个视图就临时不受 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',
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不过跨域后 csrf_token 就基本失去了原来的防止 csrf 攻击的意义,所以干脆还是直接关闭。

    多维度解决跨域问题

    刚才那些只是简单尝试发现可以,为了稳妥起见,前端后端各上一层保险方法:

    Django跨域

    1. 安装 django-cors-headers 扩展:pip install django-cors-headers
    2. 添加 appINSTALLED_APPS = ['corsheaders']
    3. 在之前注释的基础上添加新的中间件:
    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'  # 新添加的中间件
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Vue3跨域

    虽然是 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/, '')
    		},
    	}
    })
    
    • 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

    这样前端跨域代理就设置完成了。
    据看到的资料表示,这反向代理是针对 axios 的,我暂时不用这个模块,所以也不实验验证是否成功了。

    补充说明

    如果对跨域是否成功还不自信的话,可以添加以下代码让自己更安心一点,其中 * 可以改成自己的前端域名~

    response = HttpResponse('')
    response['Access-Control-Allow-Origin'] = '*'
    response['Access-Control-Allow-Credentials'] = 'true'
    
    • 1
    • 2
    • 3

    有一个深坑,就是 HBuilder X 启动的 vue 服务默认是 http://localhost:3000/ ,但这不经过网关!不经过网关就无法跨域设置 cookie !!!刚刚本博主就特别纳闷怎么回事,无意间将 localhost 改成 127.0.0.1 ,问题瞬间迎刃而解~

  • 相关阅读:
    两行TextView前面添加一个图片/控件
    JS教程之Electron.js设计强大的多平台桌面应用程序的好工具
    JVM(9)之JVM对象创建与内存分配深度剖析
    荧光定量PCR的优点和检测方法盘点
    Wordpress 如何添加 Ads.txt 文件
    [Spring Cloud] Open Feign 使用
    GBase8s分片表操作实践
    Pytorch之SwinTransformer图像分类
    数据挖掘经典十大算法_条件熵、信息增益介绍
    【AUTOSAR-COM】-10.5-APP CAN Frame/PDU“发送周期不准“的影响因素
  • 原文地址:https://blog.csdn.net/user_from_future/article/details/127853555