一、引子
我现在开启了两个django项目,分别叫Demo1和Demo2,Demo1中有一个路径‘http://127.0.0.1:8000/index/’,对应的视图是index视图返回一个index页面,页面中只有一个button按钮,按钮绑定了一个单击事件,点击之后会发送一个ajax请求,请求的路径为‘http://127.0.0.1:8001/ajax/’,Demo1的ip和端口号是:‘http://127.0.0.1:8000/’,Demo2的ip和端口号是:‘http://127.0.0.1:8001/’。前面一段描述就是在Demo1项目的一个页面向Demo2项目发送一个ajax请求,在Demo2有对应的路径和视图来处理请求,并返回值。我们运行一下。报错如下:
这就是一个已拦截的跨域请求的错误,错误内容是CORS头少“Access-Control-Allow-Origin”。这就是我们用ajax发送一个跨域请求出现的错误,这就是今天我要处理的一个问题。
二、同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能就会受到影响,可以说web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript的浏览器都会用这个策略。所谓的同源,即指:域名、端口、协议同时相同。比如说你用ajax发请求时,会检查你发送的请求是否发送路径是否ajax所在的JavaScript属于同源,即是两者的ip、端口、协议相同。如果不是同源,浏览器就会报错,提示拒绝访问。
想要实现用ajax发送跨域请求有两种方式,一是jsonp,而是cors。
三、基于JSONP的ajax跨域请求
1,版本1
我们在用script引入js代码,有时用的是网上路径,意思就是在我们的项目去请求其他项目的,如:
这种情况下是可以请求成功的,于是,我们可以运用这一功能,给button按钮绑定事件,事件的功能是创建一个script标签,然后添加到页面上,这样当我们点击button按钮就会发送一个跨域请求,而且还是允许的。
Demo1项目index.html页面上添加js代码:
function get_ele_script(url){ var ele_script=$('<script>'); ele_script.attr('src',url); ele_script.attr('id','ele_script'); $('body').append(ele_script); $('#ele_script').remove() } $('.cli').click(function () { get_ele_script('http://127.0.0.1:8001/ajax/') })
这样就成功用点击事件发送了一个跨域请求,在Demo2的视图中,有返回值,但如果我不定义返回的值,HTML文件就会报没有定义的错误,而且视图返回的值在前端页面是以变量的形式显示。
Demo2项目的视图:
def ajax(request): dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('f(%s)'%dic_json)
此时,我们就应该在HTML文件中定义f()
function f(params) {
console.log(params);
console.log(typeof params);
}
这样,当我们点击button时,会往Demo2发送一个请求,Demo2会返回带参数的f(),由于已经定义了f()函数,所以当返回时会执行这个函数,这种方法就实现了发送跨域请求,然后接受返回值,并对返回值进行处理。
2,版本2
其实版本1在Demo2项目中把返回的函数名写死了,如果照版本1,所有来反问Demo2的浏览器都会得到一个叫f()的函数,我们在声明的时候也只能写成f()。其实我们可以这样在请求的时候把我们定义的函数名一起发过去,让他就给我返回我发送过去的函数,这样,我们定义函数名就可以随意了。
Demo1项目的index.html页面上就应这样写:
function f(params) {
console.log(params);
console.log(typeof params);
}
$('.cli').click(function () {
get_ele_script('http://127.0.0.1:8001/ajax/?callbacks=f')
Demo2项目的视图:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('%s(%s)'%(a,dic_json))
3,版本3
上面两个版本就没有基于ajax请求,这个版本就基于ajax发送跨域请求。
Demo1项目下的index.html页面上:
function f(params) { console.log(params); console.log(typeof params); } $('.cli').click(function () { $.ajax({ url:'http://127.0.0.1:8001/ajax/callbacks=f', type:'GET', dataType:'jsonp', }) })
Demo2项目的视图:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) print(type(dic_json)) return HttpResponse('%s(%s)'%(a,dic_json))
4,版本4
这也是基于ajax发送的跨域请求,只是比上一版本更简单。
Demo1项目下的index.html:
function f(params) {
console.log(params);
console.log(typeof params);
}
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'GET',
dataType:'jsonp',
jsonp:'callbacks',
jsonpCallback:'f'
})
})
Demo2项目的视图:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) print(type(dic_json)) return HttpResponse('%s(%s)'%(a,dic_json))
5,版本5(终极版本)
基于ajax的跨域请求,并把返回值给ajax的success。
Demo1项目下的index.html:
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'GET',
dataType:'jsonp',
jsonp:'callbacks',
success:function (data) {
console.log(data)
}
})
})
Demo2项目下的视图:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('%s(%s)'%(a,dic_json))
这个版本就比较简单,书写方便
四、基于CORS的ajax跨域请求
最开始,我们讲的报错是:CORS头少:‘Access-Control-Allow-Origin’,既然少一个,我们就加一个,就可以了,其实这种方式才是最常用。
Demo1项目下的index.html:
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'get',
data:{'a':1},
success:function (res) {
console.log(res)
}
})
})
Demo2项目下的视图:
def ajax(request): dic = {'name': 'zhnag', 'age': 46} http=HttpResponse(json.dumps(dic)) http['Access-Control-Allow-Origin']='http://127.0.0.1:8000' #这相当于加了一个白名单,对于‘http://127.0.01:8000’的跨域请求就允许通行 return http
文摘归档
- 2019年02月(1016)
- 2019年01月(1698)
- 2016年10月(1)
- 2016年09月(11)
- 2016年07月(43)
- 2016年06月(37)
- 2016年05月(77)
- 2016年04月(62)
- 2016年03月(32)
- 2016年02月(4)
- 2016年01月(10)
- 2015年12月(3)
- 2015年11月(6)
- 2015年10月(8)
- 2015年09月(14)
- 2015年08月(453)
- 2015年07月(41)
- 2015年06月(36)
- 2015年05月(44)
- 2015年04月(46)
- 2015年03月(51)
- 2015年02月(24)
- 2015年01月(45)
- 2014年12月(34)
- 2014年11月(40)
- 2014年10月(56)
- 2014年09月(52)
- 2014年08月(66)
- 2014年07月(55)
- 2014年06月(83)
- 2014年05月(79)
- 2014年04月(64)
- 2014年03月(48)
- 2014年02月(46)
- 2014年01月(28)
- 2013年12月(63)
- 2013年11月(77)
- 2013年10月(72)
- 2013年09月(62)
- 2013年08月(83)
- 2013年07月(60)
- 2013年06月(21)
阅读排行榜
- Cocos2D-x之开发环境配置 (4688)
- TLS 协议所定义的严重错误代码是 10。Windows SChannel 错误状态是 1203 (3749)
- UART和RS232、RS485的基础知识 (3492)
- 本地文件数据加载到hive (3260)
- WAS8.0与IHS集群安装与配置指导手册 (3019)
- C/C++常见编译链接错误解决方法 (2417)
- 如何重定向Keepalived日志的输出路径 (2278)
- devstack安装报错解决方法:pkg_resources.DistributionNotFound: pip==1.4.1 (1464)
- HAProxy 研究笔记 -- HTTP请求处理-2-解析 (1205)
- iOS项目开发实战——Swift实现多个TableView的侧滑与切换 (1059)