浏览器的同源策略
-
限制了浏览器往不同的源发请求,阻止读取响应数据。
<div > <button id="btn">点我获取数据</button> </div> $('#btn').click(function () { $.ajax({ url:'http://127.0.0.1:8001/index/', success:function (res) { console.log(res) }, error:function (err) { console.log(err) } }) })
所报错误:
Access to XMLHttpRequest at 'http://127.0.0.1:8001/index' from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
-
a标签 以及form表单的 请求不会被浏览器阻止
注意 from 标签的请求地址最后的
/
<!-- a标签 实现跨域--> <a href="http://127.0.0.1:8001/index">点击获取 数据</a> <!-- form表单提交post 实现跨域--> <form action="http://127.0.0.1:8001/index/" method="post"> <input type="text" name=""> <button>提交</button> </form>
def index(request): if request.method == 'POST': print(request.POST.get('name')) return HttpResponse('form 200 OK') return HttpResponse('{}'.format('a标签请求'))
跨域
JSONP 实现
-
写法:
- 使用引用 JS 文件的 方式 给服务器发送请求
- 在引用之前定义一个函数
<script> // 定义一个 函数 用于接收返回的数据 function func(data){ console.log(data) } </script> <!-- 引用服务器的接口实现数据传递 --> <script src="http://127.0.0.1:8001/index"></script> <!-- 相当于执行 func函数 --> <script> func(data) </script>
- 在view 视图中 返回 一个
"func(data)"
函数 的 调用 字符串形式 前端会自动根据函数名调用 定义好的 函数对象并且接收数据
def index(request): import json data = {'name': '张紫益', 'age': 18} # 返回一个函数的 调用方法 return HttpResponse('index({})'.format(json.dumps(data, ensure_ascii=False)))
-
缺点:
前后端都要支持
只能发GET请求
CORS跨域
-
简单请求和非简单请求
同时满足以下两个条件的是简单请求:
(1) 请求方法是一下三种方法之一:
- HEAD
- GET
- POST
(2) HTTP 的头信息不超过一下几种字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content--Type: 只限于 application/x-www-form-urlencoded, multipart/form-data,texxt/plain
-
简单请求
前端正常 提交 ajax 请求
后端要给响应头加上
Access-Control-Allow-Origin
data = {'name': '张紫益', 'age': 18} ret = HttpResponse('{}'.format(json.dumps(data, ensure_ascii=False))) # 给 response 对象 添加响应头 指定 发送请求的主机地址 ret['Access-Control-Allow-Origin'] = 'http://localhost:63342' # 或者 让所有的 简单请求 都通过 ret['Access-Control-Allow-Origin'] = '*' // * 所有 # 启用 控制 允许 起源 return ret
-
将响应求头加入到 中间件中 避免每次都要写
from django.utils.deprecation import MiddlewareMixin class CORSMiddleware(MiddlewareMixin): def process_response(self, request, response): response['Access-Control-Allow-Origin'] = '*' return response # 注册中间件 # 在中间件的 第一行注册 因为响应 是倒叙的
-
-
非简单请求:
区别 : 前段请求的 ajax 中 加入了 contenttype: 'application/json' 的 请求头
请求的 类型 就变成了
POTIONS
类型-
后端要给响应头加上
如果修改了Content-Type:
Access-Control-Allow-Headers
前端中
$('#btn').click(function () { $.ajax({ url:'http://127.0.0.1:8001/index/', type:'post', // 设置的 非简单 请求 会 将请求方式 该为 POTIONS contentType:'application/json', success:function (res) { var aa = JSON.parse(res) console.log(aa) console.log(JSON.stringify(aa)) }, error:function (err) { console.log(err) } }) })
Django 中
data = {'name': '张紫益', 'age': 18} ret = HttpResponse('{}'.format(json.dumps(data, ensure_ascii=False))) # 判断 请求 是否是 非简单请求 if request.method =='OPTIONS': # 设置 响应头让其 通过 ret['Access-Control-Allow-Headers'] = 'content-type' return ret
PUT或DELETE请求
如果使用的是PUT或DELETE请求 :设置响应头
Access-Control-Allow-Methods
= 'PUT'data = {'name': '张紫益', 'age': 18} ret = HttpResponse('{}'.format(json.dumps(data, ensure_ascii=False))) # 判断 请求 是否是 非简单请求 if request.method =='OPTIONS': # 设置 响应头让其 通过 ret['Access-Control-Allow-Headers'] = 'content-type' # 设置 put delete 请求的 响应头 ret['Access-Control-Allow-Methods'] = 'PUT, DELETE' return ret
-
前端:
JSON 的 序列化 与反序列化
data = ' {'name': '张紫益', 'age': 18}'
// 序列化 parse 解析
var obj = JSON.parse(data)
console.log(obj)
// 反序列化
var str =JSON.stringify(obj)
console.log(str)
django-core-headers
使用django f夫人
详见博客 同源策略及JSONP、CORS跨域
安装
pip install django-cors-headers
注册APP
INSTALLED_APPS = [
...
'app01.apps.App01Config',
'corsheaders', # 将 corsheaders 这个APP注册
]
添加中间件
必须放在最前面,因为要先解决跨域的问题。只有允许跨域请求,后续的中间件才会正常执行。
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 添加中间件
'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',
]
配置
你可以选择不限制跨域访问 允许所有
CORS_ORIGIN_ALLOW_ALL = True
或者你可以选择设置允许访问的白名单
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
# '<YOUR_DOMAIN>[:PORT]',
'127.0.0.1:8080'
)