关于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编写简单的定时器的方法
May 02 Python
Python多进程并发(multiprocessing)用法实例详解
Jun 02 Python
python中(str,list,tuple)基础知识汇总
Feb 20 Python
使用Eclipse如何开发python脚本
Apr 11 Python
利用Python yagmail三行代码实现发送邮件
May 11 Python
Python图片转换成矩阵,矩阵数据转换成图片的实例
Jul 02 Python
手把手教你使用Python创建微信机器人
Apr 29 Python
python读取目录下所有的jpg文件,并显示第一张图片的示例
Jun 13 Python
Python any()函数的使用方法
Oct 28 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 Python
基于numpy中的expand_dims函数用法
Dec 18 Python
DataFrame.groupby()所见的各种用法详解
Jun 14 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
关于时间计算的结总
2006/12/06 PHP
CI(CodeIgniter)框架实现图片上传的方法
2017/03/24 PHP
浅谈Laravel模板实体转义带来的坑
2019/10/22 PHP
复制本贴标题和地址的js代码
2008/07/01 Javascript
javascript删除字符串最后一个字符
2014/01/14 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
jQuery中parentsUntil()方法用法实例
2015/01/07 Javascript
使用RequireJS优化JavaScript引用代码的方法
2015/07/01 Javascript
IE7浏览器窗口大小改变事件执行多次bug及IE6/IE7/IE8下resize问题
2015/08/21 Javascript
javascript实现五星评分功能
2015/11/10 Javascript
Eclipse引入jquery报错如何解决
2015/12/01 Javascript
浅谈js图片前端预览之filereader和window.URL.createObjectURL
2016/06/30 Javascript
微信小程序 实战实例开发流程详细介绍
2017/01/05 Javascript
纯JS实现轮播图
2017/02/22 Javascript
Angularjs 实现动态添加控件功能
2017/05/25 Javascript
基于node.js制作简单爬虫教程
2017/06/29 Javascript
使用Node.js实现简易MVC框架的方法
2017/08/07 Javascript
在微信小程序中使用mqtt服务的方法
2019/12/13 Javascript
js判断浏览器的环境(pc端,移动端,还是微信浏览器)
2020/12/24 Javascript
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
Python操作RabbitMQ服务器实现消息队列的路由功能
2016/06/29 Python
python flask中静态文件的管理方法
2018/03/20 Python
使用Python监控文件内容变化代码实例
2018/06/04 Python
Python threading的使用方法解析
2019/08/28 Python
Python实现密码薄文件读写操作
2019/12/16 Python
python opencv实现信用卡的数字识别
2020/01/12 Python
浅谈TensorFlow中读取图像数据的三种方式
2020/06/30 Python
Python中Qslider控件实操详解
2021/02/20 Python
CSS3实现自定义Checkbox特效实例代码
2017/04/24 HTML / CSS
跑步、骑行和铁人三项的高性能眼镜和服装:ROKA
2018/07/06 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
linux面试题参考答案(6)
2014/08/29 面试题
2015年纪检监察工作总结
2015/04/08 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
Vue3 Composition API的使用简介
2021/03/29 Vue.js
告别网页搜索!教你用python实现一款属于自己的翻译词典软件
2021/06/03 Python