由于浏览器的同源策略限制,不是同源的脚本不能操做其余源下面的资源,想操做另外一个源下面的资源就属于跨域了,这里说的跨域是广义跨域,咱们常说的代码中请求跨域,是狭义的跨域,即在脚本代码中向非同源域发送http请求javascript
浏览器的同源策略(SOP/same origin policy)是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,浏览器很容易受到XSS(跨站脚本攻击 cross site scripting)和CSRF(跨站请求伪造cross-site request forgery)等攻击。html
(同源 origin:协议,域名,端口号,不清楚的话,直接在浏览器控制台中输入window.location.origin看看返回值就知道了。)前端
下面两种状况,是不受跨域限制的,严格来说,这两种状况只是跨站资源请求:java
1)页面中的连接,重定向及表单提交是不受同源策略限制的python
2)跨域资源的引入,如<script src=""> <image src=""> <iframe>等web
从上面的第二种状况,咱们能够发现,但凡经过src去获取非同源状态的资源时,都是不受跨域限制的,那咱们就能够想一想,是否能够借助这种跨站资源请求的方式来实现http跨域请求呢?这就是咱们接下来要说的第一种跨域解决方案:jsonpajax
一、JSONP(不只限于python,全部的GET请求均可以使用jsonp实现跨域)json
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请求,其余请求不支持。
二、在响应头加上响应的容许跨域的参数,告诉浏览器当前请求被服务器接受,这种跨域方式也是通用的。
三、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 白名单来使用
如此,咱们的跨域处理即完成,支持全部的请求。