同源策略和解决跨域问题
===================******===================
一、同源策略
二、错误问题
1、解决方式一
2、解决方式二
三、优化
四、jQuery对JSONP的实现
五、示例
===================******===================
一、同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。
所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页
执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
二、错误问题
A项目(127.0.0.1:8000)
index.html #1、 发送Ajax请求 http://127.0.0.1:8011/user/
#3、 浏览器检测到B项目返回数据,由于浏览器安全机制同源策略,既协议,IP,端口需要相同,发现index和响应不同源,报错(CORS)
B项目(127.0.0.1:8011)
index_view() #2、 视图处理A项目请求,返回数据({'name':'luo','pwd':'123'})
1、解决方式一
B项目在返回数据时,给响应头加上
response['Access-Control-Allow-Origin'] = "*" #加上这句就行
response['Access-Control-Allow-Headers'] = 'content-type'
response['Access-Control-Allow-Methods'] = '*'
2、解决方式二
使用jsonp, 原名 jsonPadding, 原理是通过script标签的跨域特性来绕过同源策略。
JSONP 一定是GET请求,回调函数设置在url上 --> http:://127.0.0.1:8081/user/?callbacks=SayHi
方式一:
jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',
server端接受callbacks键对应值后就可以在其中填充数据打包返回了;
<button οnclick="f()">sendAjax</button>
<script>
function f(){
$.ajax({
url:"http://127.0.0.1:7766/SendAjax/",
dataType:"jsonp",
jsonp: 'callbacks',
jsonpCallback:"SayHi" # 定义
});
}
function SayHi(arg){
alert(arg);
}
</script>
#后端设置
def ajax_send2(request):
import json
callbacks=request.GET.get("callbacks") #注意要在服务端得到回调函数名的名字
s = {"name":"luo","age":18}
return HttpResponse("%s('%s')"%(callbacks,json.dumps(dic)))
方式二:
jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,
那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。
<script>
function f(){
$.ajax({
url:"http://127.0.0.1:7766/SendAjax/",
dataType:"jsonp", //必须有,告诉server,这次访问要的是一个jsonp的结果。
jsonp: 'callbacks', //jQuery帮助随机生成的:callbacks="wner"
success:function(data){
alert("hi "+data)
}
});
}
</script>
但是以上的方式也有不足。一般情况下,我们希望这个script标签能够动态的调用,
而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,
这样我们就可以灵活调用远程服务了。来看下面的优化
三、优化
===========================jQuery实现=====================
<script>
#{创建一个script标签,让他请求一次,请求完了删除他#}
//动态生成一个script标签,直接可以定义个函数,放在函数里面
function add_script(url) {
var ele_script = $("<script>");
ele_script.attr("src",url);
ele_script.attr("id","script");
$("body").append(ele_script);
$("#script").remove()
}
function xxx(name){
alert("hello"+name)
}
$(".kuayu").click(function () {
add_script("http://127.0.0.1:8080/ajax_send2/?callbacks=xxx")
});
</script>
==================js实现==========================
<button οnclick="f()">sendAjax</button>
<script>
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
document.body.removeChild(script);
}
function func(name){
alert("hello"+name)
}
function f(){
addScriptTag("http://127.0.0.1:7766/SendAjax/")
}
</script>
四、jQuery对JSONP的实现
getJSON实现:
jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法
<button οnclick="f()">sendAjax</button>
<script>
function f(){
$.getJSON("http://127.0.0.1:7766/SendAjax/?callbacks=?",function(arg){
alert("hello"+arg)
}); 匿名函数
}
</script>
注意:在url的后面必须添加一个callbacks参数,这样getJSON方法才会知道是用JSONP方式去访问服务,
callbacks后面的那个?是内部自动生成的一个回调函数名
五、示例
// 跨域请求实例
$(".jiangxiTV").click(function () {
$.ajax({
url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403",
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'list',
success:function (data) {
console.log(data.data); // [{},{},{},{},{},{}]
week_list=data.data;
$.each(week_list,function (i,j) {
console.log(i,j); // 1 {week: "周一", list: Array(19)}
s="<p>"+j.week+"列表</p>";
$(".show_list").append(s);
$.each(j.list,function (k,v) { // {time: "0030", name: "通宵剧场六集连播", link: "http://www.jxntv.cn/live/jxtv2.shtml"}
a="<p><a href='"+v.link+"'>"+v.name+"</a></p>";
$(".show_list").append(a);
})
})
}
})
})