[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros
Posted liuzhipenglove
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros相关的知识,希望对你有一定的参考价值。
浏览器的同源策略: - 同源: 同方法,同域名,同端口 http://www.baidu.com:8000 http: 方法 www.baidu.com: 域名 8000: 端口 - 定义 网上解析非常好的一篇 http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html - 限制 ajax只能发给同源的网址; 限制原理: 浏览器request--->跨域服务器 浏览器阻止接收<----跨域服务器响应, 服务器已经做出响应了,而且返回了,只是浏览器阻止接收 - 解决策略JSONP 它的基本思想是,网页通过添加一个<script>元素,请跨域请求放在src属性上 向服务器请求JSON数据 (注意数据是json,数据是通过回调函数的参数传递回来的, 所以参数必须是经过json话 ) 这种做法不受同源政策限制; 服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。 JSONP需求:向其他网站发送http请求 - 解决办法:浏览器直接发送请求(到访问其他网站)--考虑浏览器同源 - 要求: 1. 客户端 - jsonp发送url, 把funname放到url中 url?callback=myfun - 定义myfun函数 function myfun(arg) 2. 服务端 - 获取callback, fun_name = request.GET.get(\'callback\') - arg是请求,需要获取的数据,这个数据必须字符串或者是Json字符串 - 字符串 temp = \'%s(%s)\' %(fun_name, arg) 注意,如果arg是列表等类型要先arg = json.dumps(arg) - 返回字符串 return HttpResponse(temp) ps: 不是特别必要 修改django settings.py里面的ALLOWED_HOSTS = [\'http://www.s4.com\'] 修改C:\\Windows\\System32\\Drivers\\etc\\hosts里面的内容增加内容 127.0.0.1 www.s4.com 127.0.0.1 www.s5.com - 原理: 只要页面加载下面语句 <script src="http://www.s4.com:8001/user"></script> 内存中就会返回http://www.s4.com:8001/user页面内容, 并且将内容保存在内存中, 在页面的时候,会将内容当做Js渲染 当请求http://www.s4.com:8001/user?myfun=callback, 后台返回Json.dumps(\'myfun(arg)\'), 存储在浏览器内存中,就相当于调用函数 myfun(arg), 因此,需要在前端定义callback(arg),这样就不需要考虑什么时候调用函数, 为了节省空间,一般绑定一个事件动态生成script标签, function xxx(){ var tag = document.createElement(\'script\') tag.src = \'http://www.s4.com:8001/user?callback=myfun\'; document.getElementByTag(\'head\').appendChild(tag); } function myfun(arg){ console.log(arg); } # JSONP实例--动态创建script标签 # A网站前端 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="jsonp" onclick="test_jsonp();"> <script> function test_jsonp(){ var tag = document.createElement(\'script\'); tag.src = \'http://127.0.0.1:8001/users?callback=get_users\'; document.head.appendChild(tag); } function get_users(arg){ alert(123); console.log(arg) } </script> </body> </html> # B网站处理请求 url(r\'^users\', views.users), def users(request): fun_name = request.GET.get(\'callback\') user_list = json.dumps([\'alex\', \'egon\', \'eric\']) temp = "%s(%s)" % (fun_name, user_list) return HttpResponse(temp) # 用jQuery 封装JSONP, # 主要是前端不同,其他的一一致 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers();"> </body> <script src="/static/js/jquery-1.12.4.js"></script> <script> function getUsers(){ $.ajax({ url: \'http://127.0.0.1:8001/users\', type: \'GET\', dataType: \'jsonp\', jsonp: \'callback\', // 指定url传递参数名称 jsonpCallback: \'myFun\' // 指定回调函数 }) // jsonp: \'callback\', jsonCallback" :\'myFun\' // 等效于将?callback=myFun加到url上 } function myFun(arg){ console.log(arg); } </script> </html> # jQuery实现跨越的另一种方式$.getJSON() 利用getJSON来实现,只要在地址中加上callback=?参数即可 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="获取用户列表" onclick="getUsers();"> </body> <script src="/static/js/jquery-1.12.4.js"></script> <script> function getUsers(){ $.getJSON("http://127.0.0.1:8001/users?callback=?", myFun); } function myFun(arg){ console.log(arg); } </script> </html> # 使用jsonp注意: - 只能发get请求(生成script标签,里面的src肯定是get请求) - 客户端和服务端做好约定 - jsonp是一项技术,方法;目的是解决跨域问题 # 解决跨域请求的另一种方式:cors : cross site 在响应增加一个响应头:Access-Control-Allow-Origin, 这样就允许ajax跨域发送请求. 浏览器看到这个消息头,就不会阻止接收跨域返回的响应 # 视图函数 obj = HttpResponse() obj[\'Access-Control-Allow-Origin \']= \'*\' # 或者obj[\'Access-Control-Allow-Origin \']= \'www.s4.com:8000\' return obj # cros解决浏览器阻止ajax跨域问题 --简单请求 - 实例 # 前端 <body> <input type="button" value="cros支持ajax跨域发送请求" onclick="JsAjaxSend();"> </body> <script src="/static/js/jquery-1.12.4.js"></script> <script> function JsAjaxSend() { $.ajax({ url: \'http://127.0.0.1:8001/new_users\', type: \'GET\', success:function(arg){ console.log(arg) } }) } </script> # http://127.0.0.1:8001/new_users视图函数 def new_users(request): print(\'请求来了\') user_list = [\'alex\', \'egon\', \'eric\'] user_list_str = json.dumps(user_list) obj = HttpResponse(user_list_str) obj[\'Access-Control-Allow-Origin\'] = "http://127.0.0.1:8000" return obj # cros解决ajax跨域请求问题--复杂请求 复杂请求实际上发送了两个请求: OPTIONS,以及后面的复杂请求。 # 前端 function JsAjaxSend() { $.ajax({ url: \'http://127.0.0.1:8001/complicated_users\', type: \'DELETE\', success:function(arg){ console.log(arg) } }) } # 视图 --这里取消了csrf def complicated_users(request): if request.method == \'OPTIONS\': # 设置允许delete方法和浏览器接收跨域响应 obj = HttpResponse() obj[\'Access-Control-Allow-Methods\'] = \'DELETE\' obj[\'Access-Control-Allow-Origin\'] = "http://127.0.0.1:8000" return obj else: user_list_str = json.dumps([\'eric\', \'alex\']) obj = HttpResponse(user_list_str) obj[\'Access-Control-Allow-Origin\'] = "http://127.0.0.1:8000" return obj # 如何区分复杂请求和简单请求 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 注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求 # 参考博客 http://www.cnblogs.com/wupeiqi/articles/5703697.html
以上是关于[oldboy-django][2深入django]浏览器同源策略 + JSONP + cros的主要内容,如果未能解决你的问题,请参考以下文章
[oldboy-django][2深入django]老师管理--查看,添加,编辑
[oldboy-django][2深入django]初始Form组件
[oldboy-django][2深入django]点击刷新验证码
[oldboy-django][2深入django]学生管理(Form)--查看(分页)