一、同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,
如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。
所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,
结果:
二、跨域
所谓的跨域就是请求的并不是本地url,具体实例请看:
现在在项目1通过ajax访问项目2的页面(8001访问8002):
点击按钮发现并没有返回我们希望看到的,那到底是哪一步出现了问题了:
在项目2的后台,我们看到:
证明了已经处理了,难道是接收被拦截了,在火狐查看前端页面:
问题很明显就是被拦截了,为什么被拦截了?我只能说这是一种安全措施,这是在浏览器设计之初就已经规定好的,一直延续至今。
三、跨域的解决方法
在实际工作中,由于在大互联网时代,各行各业分工十分细化,单就大数据而言,
有些公司专门做数据收集、有些公司只做数据处理、而有些只做销售,这些公司传输数据的手段就是跨域请求。
下面会讲解三种解决跨域的方法:
1.借助script标签实现跨域
我们常用的Jquery可以这样:
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
在项目启动进行加载的时候,就会去对应的服务器取数据,利用这种特性可以实现跨域请求:
返回一个func(),这样在前端:
最后就能打印其中的数据了。
如果把需要传递的数据放在括号里面,就能把它取出来了,这样就可以达到跨域请求的目的了。
为了达到数据的丰富性,我们可以先进行序列化。
最后实现的代码详解:
前端代码:
<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<meta http-equiv="X-UA-Compatible" content="IE=edge"> ???<meta name="viewport" content="width=device-width, initial-scale=1"> ???<title>Title</title> ???<script src="/static/jquery-3.2.1.min.js"></script></head><body><h3>这是项目1</h3><button class="b1">send a ajax</button>{% csrf_token %}<script> ???function func(s) { ???????console.log(s) ???} ???????function cross_domain(url) {{# ???????定义一个标签,添加一个url元素,将其添加到body里面#}{# ???????为了不每次点击都会加载一个script标签,每次加载之后就删除#} ???????var $ele_script = $("<script>"); ???????$ele_script.attr("src",url); ???????$ele_script.attr("class","cs"); ???????$("body").append($ele_script); ???????$(".cs").remove() ???}{# ???点击按钮的时候就会触发,此时才会加载<script>#}{# ???使用callback=func可以将后端传输字符串进行解耦,在后端可以接收callback,这样再传递func()到前端#} ???$(".b1").click(function () { ???????cross_domain("http://127.0.0.1:8002/ajax_send/?callback=func") ???})</script></body></html>
后端代码:
from django.shortcuts import render,HttpResponsedef index(request): ???return render(request,"index.html")import jsondef ajax_send(request): ???dict = {"name":"kebi"} ???func =request.GET.get("callback") ?#这样可以不用固定函数名 ???return ?HttpResponse("%s(%s)"%(func,json.dumps(dict)))
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,
然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。
我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。
2.jQuery对JSONP的实现
(1)getJSON
jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法:
项目一前端部分:
<script> ???$(".b1").click(function () { ???????$.getJSON("http://127.0.0.1:8002/ajax_send/?callback=?",function (data) {{# ???????????callback=?这个值系统会帮你随机生成,就相当于让面的ross_domain#}{# ???????????当拿到结果之后,只会执行function ()这个匿名函数#} ???????????console.log(data) ???????}) ???})</script>
项目二后端部分:
import jsondef ajax_send(request): ???dict = {"name":"kebi"} ???func =request.GET.get("callback") ???print("func",func) ?#func jQuery3210924015436172589_1519900847362 ???print("项目2.。。") ???return ?HttpResponse("%s(%s)"%(func,json.dumps(dict)))
经过测试可以知道,这种方法也是可以的,其实就是对script的封装。
结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,
callback后面的那个问号是内部自动生成的一个回调函数名。
此外,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现
(2)$.ajax
看到这个有些人就疑惑,这个不就是Ajax吗,不是说ajax不行吗,这咋就又行了?
其实确实不行,只是Jquery的作者让它和ajax同名而已。
项目一前端:
<script>$(".b1").click(function () { ??$.ajax({ ??????url:‘http://127.0.0.1:8002/ajax_send/‘, ??????dataType:"jsonp", ??{# 期待数据类型,一定要加,只要有这句话,就会去添加script标签 #} ??????jsonp: ‘callback‘, ?{# 其实就是补充在后面:http://127.0.0.1:8002/ajax_send/?callback=SayHi#} ??????jsonpCallback:"SayHi" ?{# 如果这里不加jsonpCallback,就会是callback=?,这样就是getJson #} ??});});function SayHi(data) { ???console.log(data)}</script>
项目二后端:
def ajax_send(request): ???dict = {"name":"kebi"} ???func =request.GET.get("callback") ???print("func",func) ?#func SayHi ???print("项目2.。。") ???return ?HttpResponse("%s(%s)"%(func,json.dumps(dict)))
当然,最简单的形式还是通过回调函数来处理(推荐):
<script>$(".b1").click(function () { ??$.ajax({ ??????url:‘http://127.0.0.1:8002/ajax_send/‘, ??????dataType:"jsonp", ?????????jsonp: ‘callback‘, ???????success:function (data) { ??????????console.log(data) ??????} ??});});</script>
jsonp: ‘callbacks‘就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名‘SayHi‘,
server端接受callback键对应值后就可以在其中填充数据打包返回了;
jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。
利用jQuery可以很方便的实现JSONP来进行跨域访问。
注意:JSONP一定是GET请求
最后来一个跨域请求的实例:
<input type="button" onclick="AjaxRequest()" value="跨域Ajax" /><div id="container"></div> ???<script type="text/javascript"> ???????function AjaxRequest() { ???????????$.ajax({ ???????????????url: ‘http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403‘, ???????????????type: ‘GET‘, ???????????????dataType: ‘jsonp‘, ???????????????jsonp: ‘callback‘, ???????????????jsonpCallback: ‘list‘, ???????????????success: function (data) { ???????????????????$.each(data.data,function(i){ ???{# 循环 #} ???????????????????????var item = data.data[i]; ???????????????????????var str = "<p>"+ item.week +"</p>"; ??{# 添加日期标签 #} ???????????????????????$(‘#container‘).append(str); ???????????????????????$.each(item.list,function(j){ ??{# 循环 #} ???????????????????????????var temp = "<a href=‘" + item.list[j].link +"‘>" + item.list[j].name +" </a><br/>"; ???????????????????????????$(‘#container‘).append(temp); ???????????????????????}); ???????????????????????$(‘#container‘).append("<hr/>"); ???????????????????}) ???????????????} ???????????}); ???????}</script>
Ajax跨域请求
原文地址:https://www.cnblogs.com/yangmingxianshen/p/8490221.html