同源策略jsonp和cors
同源策略:
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
项目1
=================http://127.0.0.1:8001项目的index============ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> <button>ajax</button> {% csrf_token %} <script> $("button").click(function(){ $.ajax({ url:"http://127.0.0.1:8002/SendAjax/", type:"POST", data:{"username":"man","csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()}, success:function(data){ alert(123); alert(data); } }) }) </script> </body> </html>
项目2
==================http://127.0.0.1:8002项目的index================ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> <button>sendAjax</button> {% csrf_token %} <script> $("button").click(function(){ $.ajax({ url:"/SendAjax/", type:"POST", data:{"username":"man","csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()}, success:function(data){ alert(data) } }) }) </script> </body> </html> ===================http://127.0.0.1:8002项目的views==================== def index(request): return render(request,"index.html") from django.views.decorators.csrf import csrf_exempt @csrf_exempt def SendAjax(request): # 不校验csrf_token import json return HttpResponse(json.dumps("hello2"))
当点击项目1的按钮时,发送了请求,但是会发现报错如下:
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8002/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')
如何解决同源策略实现跨域请求
使用script标签来完成跨域请求 原理是通过script标签的跨域特性来绕过同源策略。
# =============================http://127.0.0.1:8001/index <button>ajax</button> {% csrf_token %} <script> function func(name){ alert(name) } </script> <script src="http://127.0.0.1:8002/SendAjax/"></script> # =============================http://127.0.0.1:8002/ from django.views.decorators.csrf import csrf_exempt @csrf_exempt def SendAjax(request): import json # dic={"k1":"v1"} return HttpResponse("func('param')") # return HttpResponse("func('%s')"%json.dumps(dic))
使用jsonp来实现跨域请求
================http://127.0.0.1:8001/index=== <button class="get_index" onclick=f()>洗剪吹</button> <srcipt>
function ret(arg) {
console.log(arg)
}
$(".get_index").click(function () { $.ajax({ url:"http://127.0.0.1:8002/index/", type:"get", dataType:"jsonp", // 伪造ajax 基于script jsonp: 'callbacks', //jsonpCallback:"ret", success:function (data) { console.log(data) } }) }) </srcipt> =================127.0.0.1:8002/index==== def index(request): # jsonp func=request.GET.get("callbacks") # print("func",func) info={"name":"man","age":34,"price":200} return HttpResponse(" ('%s')"%(func,json.dumps(info)
jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'ret',server端接受callback键对应值后就可以在其中填充数据打包返回了;
jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。
jsonp应用
$(".get_index").click(function () { $.ajax({ url:"http://www.jxntv.cn/data/jmd-jxtv2.html", type:"get", dataType:"jsonp", // 伪造ajax 基于script jsonp: 'callbacks', jsonpCallback:"list", success:function (data) { //console.log(data.data); var html=""; $.each(data.data,function (index,weekday) { console.log(weekday); // {week: "周一", list: Array(19)} html+='<p>'+weekday.week+'</p>'; $.each(weekday.list,function (j,show) { html+= '<p><a href='+show.link+'>'+show.name+'</a></p>' }) }); $("body").append(html) } }) })
使用cors来实现跨域请求
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
============127.0.0.1:8001=====
$(".get_service").click(function () {
$.ajax({
url:"http://127.0.0.1:8008/service/",
success:function (data) {
console.log(data)
}
})
})
==============127.0.0.1:8002======
def service(request):
info = {"k1":"v1","k2":"v2"}
responce = HttpResponce(json.dumps(info))
responce["Access-Control-Allow-Origin"] = "http://127.0.0.1:8001"
responce["Access-Control-Allow-Origin"] = "*" #表示所有访问通过
return responce