刨析Django----跨域corsheaders

     阅读:50

前后端分离

前端服务器,返回页面、样式等
后端服务器,返回数据。

同源与跨域

浏览器的同源策略,
协议、地址、端口号均相同,即为同源;
否则为非同源,即跨域
在这里插入图片描述
在这里插入图片描述
简单请求(simple request)

  1. 请求方法为GET/POST/HEAD
  2. 请求头有Accept/Accept-Language/Content-Language/Content-Type
    且Content-Type值(application/x-www-form-urlencoded; multipart/form-data;text/plain)
    同时满足以上要求的才是简单请求;否则为预检请求(preflight request),即复杂请求

 
 
简单请求的头部中有Origin,若允许跨域,则响应头中有Access-Control-Allow-Origin
允许请求携带Cookie,则响应头中有Access-Control-Allow-Credentials

在这里插入图片描述
预检请求,流程:

  1. 先发送OPTIONS请求,请求头
    Origin
    Access-Control-Request-Method
    Access-Control-Request-Headers
    针对OPTIONS的响应,头部有:
    Access-Control-Allow-Origin 允许跨域
    Access-Control-Allow-Methods 允许跨域的方法
    Access-Control-Allow-Headers 允许跨域的请求头
    Access-Control-Allow-Credentials 允许携带Cookie

  2. 主请求, POST or …

两步走太麻烦,响应头中加入Access-Control-Max-Age,设置OPTIONS请求的缓存时间,在此期间不再发送OPTIONS请求。

响应头中有set-cookie,但是浏览器中却没有存储

前端使用Vue+axios直接跨域请求django,响应头中有set-cookie,但是浏览器应用中cookie没有存储。
在这里插入图片描述
解决:配置Vue代理
在Vue项目的根目录创建一个vue.config.js配置文件,启动项目时,自动加载该配置文件。

//vue.config.js
module.exports = {
	devServer:{
		proxy:'http://127.0.0.1:8000'
	}
}

然后所有的请求都会被vue代理到http://127.0.0.1:8000。
注意需重启vue项目

暂存问题:

  1. 删除session, 浏览器的sessionid不会删除,但可以实现退出功能的效果;
    在这里插入图片描述
    httpOnly=True,防止js读取cookie,提高cookie的安全性,降低XSS(跨站脚本攻击)的攻击的风险res.set_cookie(key,value,max_age,httpOnly=True)

  2. delete_cookie,浏览器无效果,可以set_cookie设置1s过期解决无法删除的问题。

Django配置跨域请求

只需在Django服务端,简单配置

  1. 安装django-cors-headers
#安装第三方应用
pip3 install django-cors-headers
  1. 配置django>settings.py
INSTALLED_APPS = [
	...,
	'corsheaders',
	'rest_framework',
]

MIDDLEWARES = [
	...,
	'corsheaders.middleware.CorsMiddleware', #注意在common的上方,官方建议
    'django.middleware.common.CommonMiddleware','
]


#允许前端请求携带Cookie(含sessionid)
CORS_ALLOW_CREDENTIALS = True  #会话保持必须

# CORS_ORIGIN_ALLOW_ALL = True  #允许所有的源跨域到django
CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1:5000', #格式严格
) #[]也可以

#非必须
CORS_ALLOW_METHODS = (
    "GET",
    "POST",
    "PUT",
    "DELETE",
    'OPTIONS'
    'PATCH',
    'VIEW'
)

#非必须
CORS_ALLOW_HEADERS = (
    "XMLHttpRequest",
    'token',
    'X_FILENAME',
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)
#暴露响应头,xhr才可以拿到响应头
CORS_EXPOSE_HEADERS = (
	'token',
)
#缓存options请求
CORS_PREFLIGHT_MAX_AGE = 86400  #秒

应用案例

前后端分离的方式,实现基于Django的用户的注册功能。

需求分析

  1. 基于Flask搭建前端服务器,用户发送GET请求,返回注册页面。
  2. 基于Django搭建后端服务器,用户提交注册数据,后端接收并保存用户数据。
  3. UI界面如下:
    在这里插入图片描述

概要设计

  1. 整体架构图
    pending
  2. 技术选择
    Django长期支持版,
    2.2----->最新补丁版本2.2.25
    3.2----->最新补丁版3.2.10
    官网建议更新到最新的补丁版
#win 更新
python -m pip install django==3.2.10 -i https://pypi.tuna.tsinghua.edu.cn/simple/
#以上通过-i 使用清华源

#linux
sudo pip3 install django==2.2.25 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

这里采用:
Ubuntu1804
python_3.6
Django_2.2.25
Flask_1.1.2
mysql_5.7
redis

详细设计

GET http://localhost:5000/user/register/
前端服务器返回register.html页面
POST http://localhost:8000/user/register/
后端接收并保存用户的注册数据,若用户已存在,则返回响应‘用户名已注册’;否则返回响应 ‘注册OK’

数据库设计

这里后端需要有一个数据库及表 来存储用户的注册数据。
采用mysql数据库,连接mysql服务,创建一个数据库(如lauf),然后在Django中配置mysql即可。
表设计
在这里插入图片描述

编码实现

  1. 搭建前后端的虚拟环境
#安装虚拟环境模块
sudo apt-get install python3-venv  #失败多试几次
#创建前端虚拟环境
python3 -m venv frontenv
cd frontenv/bin
source ./activate  #激活虚拟环境
pip install flask==1.1.2   #pip list/ pip freeze 查看安装的包

#创建后端虚拟环境
python3 -m venv backenv

然后将虚拟环境移动到~/.virtualenvs,便于在开发环境中使用。

  1. 搭建前端服务器
    使用vscode处理前端服务,并配置frontenv虚拟环境,配置方法参考flask框架介绍
     
    链接:代码参考
    提取码:97t5

  2. 搭建后端服务器
    使用pycharm处理后端服务,并配置backenv虚拟环境
     
    链接:代码参考
    提取码:306t

遇到的问题

  1. 跨域没有配置好
    在这里插入图片描述
  2. 未禁用csrf中间件
    在这里插入图片描述
  3. 返回的不是Json响应
    在这里插入图片描述
  4. 服务端未启动
    在这里插入图片描述