Django框架基础之跨域
由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。
特别的:由于同源策略是浏览器的限制,所以请求的发送和响应是可以进行,只不过浏览器不接受罢了。
浏览器同源策略并不是对所有的请求均制约:
制约: XmlHttpRequest
不约束: img、iframe、script等具有src属性的标签
开发需求:向其他网站发http请求
-- 浏览器直接发送请求(考虑同源)
--制造含有src属性的标签,绕过同源策略机制(jsonp)
--加响应头,使浏览器允许跨域(core)
-- 浏览器--服务端---发送请求
JSONP(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性(浏览器允许script标签跨域)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a onclick="show()">发送</a> <input type="button" value="获取用户列表" onclick="getUsers()"> <head></head> <script src="/static/jquery-3.2.1.js"></script> <script> function show(){ var tag=document.createElement('script'); tag.src="http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403"; document.head.appendChild(tag); } //自己写动态创建script function getUsers(){ var tag=document.createElement('script'); tag.src='http://www.s4.com:8000/users/?callback=bbb'; document.head.appendChild(tag) } function bbb(data){ console.log(data) } //利用jquery发送jsonp请求 function getUsers(){ $.ajax({ url:'http://www.s4.com:8000/users/', type:'GET', dataType:'JSONP', jsonp:'callback', jsonpCallback:'bbb' }) } function bbb(data){ console.log(data); } </script> </body> </html>
#jsonp 实现跨域请求 def users(request): v=request.GET.get('callback') print('请求来了') user_list=[ 'alex','eric','egon' ] user_list_str=json.dumps(user_list) temp='%s(%s)'%(v,user_list_str) print(temp) return HttpResponse(temp)
随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers()"> <script src="/static/jquery-3.2.1.js"></script> <script> //cors跨站资源共享--直接发送请求获取资源 function getUsers(){ $.ajax({ url:'http://www.s4.com:8000/newusers/', type:'GET', success:function (data) { console.log(data); } }) } //core 复杂请求 function getUsers(){ $.ajax({ url:'http://www.s4.com:8000/core/', type:'DELETE', success:function (data) { console.log(data); } }) } </script> </body> </html>
#core 添加响应头 实现跨域简单请求 def newusers(request): user_list = [ 'alex', 'eric', 'egon' ] user_list_str = json.dumps(user_list) obj = HttpResponse(user_list_str) obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8001' return obj #core 添加响应头 实现跨域复杂请求 def core(request): if request.method=='OPTIONS': obj=HttpResponse() obj['Access-Control-Allow-Origin']='http://127.0.0.1:8001' obj['Access-Control-Allow-Methods']='DELETE' return obj obj=HttpResponse('jjjjjj') obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8001' return obj
* 简单请求 OR 非简单请求
条件: 1、请求方式:HEAD、GET、POST 2、请求头信息: Accept Accept-Language Content-Language Last-Event-ID Content-Type 对应的值是以下三个中的任意一个 application/x-www-form-urlencoded multipart/form-data text/plain 注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求 * 简单请求和非简单请求的区别? 简单请求:一次请求 非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。 * 关于“预检” - 请求方式:OPTIONS - “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息 - 如何“预检” => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过 Access-Control-Request-Method => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过 Access-Control-Request-Headers