关于python 跨域处理方式详解


Posted in Python onMarch 28, 2020

因为浏览器的同源策略限制,不是同源的脚本不能操作其他源下面的资源,想操作另一个源下面的资源就属于跨域了,这里说的跨域是广义跨域,我们常说的代码中请求跨域,是狭义的跨域,即在脚本代码中向非同源域发送http请求

浏览器的同源策略(SOP/same origin policy)是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS(跨站脚本攻击 cross site scripting)和CSRF(跨站请求伪造cross-site request forgery)等攻击。

(同源 origin:协议,域名,端口号,不清楚的话,直接在浏览器控制台中输入window.location.origin看看返回值就知道了。)

下面两种情况,是不受跨域限制的,严格来讲,这两种情况只是跨站资源请求:

1)页面中的链接,重定向及表单提交是不受同源策略限制的

2)跨域资源的引入,如<script src=""> <image src=""> <iframe>等

从上面的第二种情况,我们可以发现,但凡通过src去获取非同源状态的资源时,都是不受跨域限制的,那我们就可以想想,是否可以借助这种跨站资源请求的方式来实现http跨域请求呢?这就是我们接下来要说的第一种跨域解决方案:jsonp

1、JSONP(不仅限于python,所有的GET请求都可以使用jsonp实现跨域)

1)实现原理:

从上面的分析我们已经知道,web页面上请求跨站资源请求是不会受到同源策略限制的,所有我们会想,我们可不可以在服务器上想办法把web端需要的数据装进一个js文件里面,然后让web端直接访问这个js文件,从而获取需要的数据呢?恰巧我们知道有一种叫做json的数据格式,且js原生支持,所以web端就可以通过像访问js脚本一样的方式,来调用跨域服务器上动态生成的js文件。

为了便于客户端使用数据,逐渐形成一种非正式传输协议:JSONP。JSONP的一个要点就是,传给服务器一个callback参数,然后服务器返回数据时,将这个callback参数作为函数名来包裹住json数据

2)jsonp实例

在远程服务器上新建一个remote.js文件:

HandleRemote({"title":"哈哈", "name":"我是一个测试数据哦!"})

在本地新建html文件:

function HandleRemote(data){
console.log(data.title+data.name);
}
<script type="text/javascript" src="远程服务器地址/remote.js">

运行本地文件,在浏览器的控制台可以看到 哈哈我是一个测试数据哦! 的输出

到现在我们已经实现了去服务器上获取数据,剩下还有两个问题需要我们思考:

a、我们如何让远程服务器知道他要调用的本地函数回调函数的名字是什么?

b、我们如何在远程服务器上动态生成js脚本

有了思路就很好办了,先看第一个问题:

我们如何让服务器知道我们本地的回调函数名?告诉他就行了啊,在请求中加上我们的函数名,然后让远程服务器根据我们的参数取动态生成js脚本调用函数名即可!

前端实现

var url = "http://test.com/getRemoteDate?callback=HandleRemote"
var script = document.createElement("script");
script.setAttribute("src", url)
document.getElementByTagName("head")[0].appendChild(script);

最后将上面的代码封装成通用的ajax形式:

url = "http://test.com/getRemoteDate/";
$.ajax({
url:url,
type:"GET",
dataType:"JSONP",
jsonp:"callback", #将会作为参数传给服务器,用于获得回调函数的参数名
jsonCallback:"test", # 自定义的jsonp的回调函数参数名,默认为jQuery自动生成的函数名,也可以自定义,jQuery会自动为你处理的。
success:function(data){
此处data即为返回的json数据了,前端根据需要自行处理
} 
});

服务端代码 :

def getData():
return {"title":"哈哈", "name":"这又是一个测试数据哦!"}
def getRemote(request):
funcName = request.GET.get("callback")
result = getData()
# 将结果以json形式返回,与前端的jsonp交互
return funcName+"("+json.dumps(result)+")"

配置url:

url(r"^getRemoteData/$", getRemote)

到这里,jsonp就完成了,虽然jsonp不受同源策略的限制,但是jsonp有个问题,就是它只支持GET请求,其他请求不支持。

2、在响应头加上响应的允许跨域的参数,告诉浏览器当前请求被服务器接受,这种跨域方式也是通用的。

3、python Django中最常用的另一种处理跨域的方式:

使用Django提供的 Django-cors-headers 来处理跨域

从GitHub上面下载Django-cors-headers

pip install Django-cors-headers.zip

在settings.py中的中间件中配置 【'corsheaders.middleware.CorsMiddleware',】记得这个中间件一定要写在CSRF之前,为了方便处理,一般写在最前面

设置 CORS_ORIGIN_ALLOW_ALL = True,即允许所有的跨域请求,当然,这里也可以设置为False,然后配合 CORS_ORIGIN_WHITELIST 白名单来使用

如此,我们的跨域处理即完成,支持所有的请求。

补充知识:python WSGI 解决跨域问题

import json
from wsgiref.simple_server import make_server

# application()函数是Python中符合WSGI标准的一个HTTP处理函数,返回是一个字符串
def application(environ, start_response):
 # start_response 如下调用就会发送HTTP响应的Header,注意只能调用一次start_response()函数发送Header。
 # start_response 函数两个参数,一是HTTP响应码,一是一组list表示的HTTP Header,每个Header用一个包含两个str的数组表示
 status = '200 OK'
 # response_headers 中添加请求头部 ,解决跨域问题 
 response_headers = [('Content-type', 'application/json'),
   ('Access-Control-Allow-Origin', '*'),
   ('Access-Control-Allow-Methods', 'POST'),
   ('Access-Control-Allow-Headers', 'x-requested-with,content-type'),
   ] # json 
 start_response(status, response_headers)
 result = {'code': 200, 'message': "You get the flag"}
 return [result.encode()]
 
if __name__ == "__main__":
 port = 8091
 httpd = make_server("127.0.0.1", port, application)
 print("serving http on port {0}...".format(str(port)))
 httpd.serve_forever()

以上这篇关于python 跨域处理方式详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中使用pyhook实现键盘监控的例子
Jul 18 Python
Python XML RPC服务器端和客户端实例
Nov 22 Python
Python re模块介绍
Nov 30 Python
python实现比较两段文本不同之处的方法
May 30 Python
详解Numpy中的广播原则/机制
Sep 20 Python
对Python中内置异常层次结构详解
Oct 18 Python
Windows 8.1 64bit下搭建 Scrapy 0.22 环境
Nov 18 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
Dec 03 Python
python实现图像检索的三种(直方图/OpenCV/哈希法)
Aug 08 Python
Python打印特殊符号及对应编码解析
May 07 Python
浅析Python 条件控制语句
Jul 15 Python
tensorflow+k-means聚类简单实现猫狗图像分类的方法
Apr 28 Python
对python中各个response的使用说明
Mar 28 #Python
基于Django signals 信号作用及用法详解
Mar 28 #Python
浅谈django 模型类使用save()方法的好处与注意事项
Mar 28 #Python
Django 实现对已存在的model进行更改
Mar 28 #Python
浅谈Django QuerySet对象(模型.objects)的常用方法
Mar 28 #Python
django使用F方法更新一个对象多个对象字段的实现
Mar 28 #Python
Django 拼接两个queryset 或是两个不可以相加的对象实例
Mar 28 #Python
You might like
PHP has encountered an Access Violation
2007/01/15 PHP
php !function_exists(&quot;T7FC56270E7A70FA81A5935B72EACBE29&quot;))代码解密
2011/01/07 PHP
WordPress中缩略图的使用以及相关技巧
2015/11/24 PHP
PHP封装的非对称加密RSA算法示例
2018/05/28 PHP
表单元素事件 (Form Element Events)
2009/07/17 Javascript
HTML5之lang属性与dir属性的详解
2013/06/19 Javascript
JavaScript获取FCK编辑器信息的具体方法
2013/07/12 Javascript
JS不间断向上滚动效果代码
2013/12/25 Javascript
JS控制输入框内字符串长度
2014/05/21 Javascript
JavaScript类型系统之Object详解
2016/01/07 Javascript
JQuery validate插件Remote用法大全
2016/05/15 Javascript
js操作XML文件的实现方法兼容IE与FireFox
2016/06/25 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
2016/07/15 Javascript
使用原生的javascript来实现轮播图
2017/02/24 Javascript
利用Mongoose让JSON数据直接插入或更新到MongoDB
2017/05/03 Javascript
Vue.js列表渲染绑定jQuery插件的正确姿势
2017/06/29 jQuery
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
bootstrap datetimepicker控件位置异常的解决方法
2017/11/23 Javascript
mockjs+vue页面直接展示数据的方法
2018/12/19 Javascript
详解keep-alive + vuex 让缓存的页面灵活起来
2019/04/19 Javascript
解决ele ui 表格表头太长问题的实现
2019/11/13 Javascript
Element实现表格嵌套、多个表格共用一个表头的方法
2020/05/09 Javascript
python正则匹配查询港澳通行证办理进度示例分享
2013/12/27 Python
python实现超简单端口转发的方法
2015/03/13 Python
用Python编写一个简单的FUSE文件系统的教程
2015/04/02 Python
使用python对文件中的数值进行累加的实例
2018/11/28 Python
python自制包并用pip免提交到pypi仅安装到本机【推荐】
2019/06/03 Python
wxpython绘制圆角窗体
2019/11/18 Python
HTML5 语音搜索只需一句代码
2013/01/03 HTML / CSS
电子信息专业自荐书
2014/02/04 职场文书
知识竞赛主持词
2014/03/26 职场文书
重阳节标语大全
2014/10/07 职场文书
员工旷工检讨书
2015/08/15 职场文书
2016大学迎新晚会开场白
2015/11/24 职场文书
标准版个人借条怎么写?以及什么是借条?
2019/08/28 职场文书
Go语言安装并操作redis的go-redis库
2022/04/14 Golang