Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery

基于jQuery的Ajax实现:

jQquery中创建XMLHttpRequest对象就没有兼容性问题了,而且不需要前面的四个步骤,直接使用 . a j a x ( ) , 通 过 设 置 相 关 的 参 数 , 如 提 交 的 方 法 , u r l , 数 据 等 , 一 次 性 完 成 所 有 步 骤 及 功 能 。 .ajax(),通过设置相关的参数,如提交的方法,url,数据等,一次性完成所有步骤及功能。 .ajax()url.ajax()是jQuery实现ajax的最底层方法。

$.ajax(
url:
type:“POST” or “GET”

)

高级一些的封装:

$.get() :直接就体现了GET提交
$.post() :直接接体现了POST提交

上面是在 . a j a x ( ) 基 础 上 的 更 高 级 封 装 , 上 述 的 方 法 至 少 不 需 要 设 置 提 交 方 法 参 数 了 。 < 1 > .ajax()基础上的更高级封装,上述的方法至少不需要设置提交方法参数了。 <1> .ajax()<1>.get(url, [data], [callback], [datatype])
<2>$.post(url, [data], [callback], [datatype]) //datatype: text|html|json|script,数据的类型,要求后台返回的数据的类型。

不提交数据时两种方法的请求头:




    
    Title








def jqueryajax(req):
    return render(req,"jqueryajax.html")

def jqajaxtest(req):
    print("req.GET:",req.GET)
    return HttpResponse("ok111")

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第1张图片

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第2张图片

由上面两个结果,只是请求方法不同。

传递数据:

get修改参数:
1) $.get(“/app01/jqajaxtest/a=bbq&b=10”) $.get()的第一种传递数据方式,直接拼接网址后

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第3张图片

后台打印:

2) $.get(“/app01/jqajaxtest/”,{name:‘bbq’,a:100}) $.get()的第二种传递数据方式,参数第二个位置。

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第4张图片

结果与第一种相同,ajax将参数的字典键值对给拼接到了请求网址的后面。

post修改参数:

1)$.post(“/app01/jqajaxtest/”,{aa:‘小老虎’,bb:23}) POST方法传递数据,数据在第二个参数位置

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第5张图片

2)$.post(“/app01/jqajaxtest/”,{aa:‘小花猫’,bb:44},function (data) {
alert(data); }),增加第三个参数,回调函数

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第6张图片

回调函数就是POST方法执行完毕后,再调用执行这个函数,函数的参数data接收POST方法返回的数据,就是后台jqajaxtest(req)返回的数据,即ok111。

还有第四个参数,是数据类型,是告诉后台返回给前端的数据类型,如果不匹配,则回调函数不执行。

关于回调函数,其参数都有哪些呢?可以使用arguments参数来查看:
$.post(“/app01/jqajaxtest/”,{aa:‘小花猫’,bb:44},function (data) { console.log(arguments); })

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第7张图片

显示参数公有3个,分别是ok111,success和{…},其中上面写的data对应第一个参数,第二个参数是状态信息,两个值‘success’和‘error’,第三个参数是一个对象,这个对象就是XMLHttpRequest对象。

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第8张图片

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第9张图片

. g e t J s o n ( ) 相 当 于 .getJson() 相当于 .getJson().get( ,datatype=Json)
. g e t s c r i p t ( ) 用 于 即 时 加 载 文 件 , 作 用 类 似 < s c r i p t s r c = " " / > , 区 别 是 < s c r i p t s r c = " " / > 是 在 网 页 加 载 时 就 加 载 完 成 了 , 而 .getscript() 用于即时加载文件,作用类似 {# 上面的语句src使用了完整的路径名,并且不同源,即协议+IP+端口与请求不同 #} def jqajaxtest(req): import json print("req.GET:",req.GET) print('req.POST:',req.POST) return HttpResponse("hello")

关键就是这一句。

我们同样的项目在不同的端口上启动,一个在8000,一个在8001。

然后访问http://127.0.0.1:8000/app01/jqueryajax/,此时在执行到时,就进行了跨域的访问了。

在浏览器中访问结果如下:

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第16张图片

出现了错误信息,CORB屏蔽MIME类型为text/html的响应。

修改一下:




    
    Title






{# 上面的语句src使用了完整的路径名,并且不同源,即协议+IP+端口与请求不同 #}




def jqajaxtest(req):
    import json
    print("11111111111111")
    print("req.GET:",req.GET)
    print('req.POST:',req.POST)
    dic = {'key1':12345}
    # HttpResponse.status_code = '400'
    print(HttpResponse().get(header="X-Content-Type-Options"))
    # print("===:",HttpResponse.has_header("X-Content-Type-Options"))
    # return HttpResponse("hello")
    return HttpResponse("ff1('kkk');",headers={"Content-Type":"text/javascript",})

运行结果:

Python入门自学进阶-Web框架——8、认识Ajax,与Django交互,基于jQuery_第17张图片

对于语句:

跨域请求成功,返回了 ff1(‘kkk’);,并作为JavaScript语句执行,因为网页中定义了ff1(w)函数,就把跨域的数据"kkk"打印出来了。

关键是设置HTML头:headers={“Content-Type”:“text/javascript”,},否则会被CORB阻塞。

以上就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调

将JSON数据填充进回调函数,这应该就是JSONP的JSON+Padding的含义吧。

一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。




上面的代码实际上就是在点击按钮时生成

以上的代码默认后台知道前端的函数,如果后台不知道呢?这就需要前端将函数名传给后台:






----------------------views.py
def get_byjsonp(req):

    func=req.GET.get("callbacks")

    return HttpResponse("%s('yuan')"%func)  #后台动态的调用前端的函数,根据前端传来的函数名调用。

jQuery对JSONP的实现

jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法:


这里的callback=?,在后台,会收到键值对callback=“dfsafds’”,是一个随机的字符串,作为函数名,前端知道其与后边的function(arg)是关联的,相当于一个匿名函数的名。

要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。

此外,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现:




 
#--------------------------------- http://127.0.0.1:8002/get_byjsonp
 def get_byjsonp(req):

    callback=req.GET.get('callbacks')
    print(callback)
    return HttpResponse('%s("yuan")'%callback)

上面的jsonp: ‘callbacks’,和jsonpCallback:“SayHi”,最终会拼接成:callbacks=“SayHi”,即指明函数名。

最简单的形式还是通过回调函数来处理:




 #-------------------------------------http://127.0.0.1:8002/get_byjsonp
def get_byjsonp(req):

    callbacks=req.GET.get('callbacks')
    print(callbacks)                 #wner  

return HttpResponse("%s('yuan')"%callbacks)

jsonp: ‘callbacks’就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名’SayHi’,server端接受callback键对应值后就可以在其中填充数据打包返回了;

jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。

利用jQuery可以很方便的实现JSONP来进行跨域访问。

==================================================

关于CORB——Cross-Origin Read Blocking,跨域读阻塞,是一个新的 web 平台安全功能, 它能够帮助减少线程之间的旁路攻击(side-channel attacks);

CORB 的目的是防止浏览器向网页接收某些跨源网络响应,因为这些响应可能包含敏感信息,而且现有的网页功能不需要这些响应。

例如: 它将清除一个从

允许加载跨域资源, 意味着存在着安全隐患:
场景: 用户登录了 victim.com 之后, 又去访问了 evil.com 的恶意站点.
在 evil.com 中有

CORB 会在敏感信息加载到页面内存之前,将其拦截掉,如此,敏感信息既不会暴露于浏览器,也不会进驻内存空间,得到了很好的保护。

CORB 可以减少下面的攻击
Cross-Site Script Inclusion (XSSI)
XSSI 是一种攻击方式. 它通过

CORB 阻止了这一类攻击, 因为 CORB 将阻止

通过 CPU 预测执行,而引起的旁路攻击 (例如 Spectre).
例如: 攻击者会使用 img标签来加载跨域的文件, 让 JavaScript 在执行过程中, 将进程中的信息暴露给攻击者

CORB 通过阻止 JSON 的资源加载到进程的内存中, 可以阻止这一类攻击.

CORB 是如何阻止响应的呢
当 CORB 判断出需要对响应做出 CORB-protected, 响应则会

响应体被替换为空值
响应头被移除
为了有效地对抗预测执行的旁路攻击,CORB 阻塞必须在响应到达承载跨源请求发起者的进程之前发生。

CORB 不会影响的内容
CORB 并不会影响下面的情况

  • navigation requests或者请求的request destination 是"document", “embed”, “frame”, “iframe”, 或者 “object”.
  • Download requests :
  • XHR and fetch()
  • ping, navigator.sendBeacon()

什么样的内容会被 CORB-protected
当跨域请求回来的数据 MIME type 同跨域标签应有的 MIME 类型不匹配时,浏览器会启动 CORB 保护数据不被泄漏.
例如: script 标签请求的响应是 json. img 标签请求回来的是 json.

目前, 针对下面的响应类型会触发 CORB

  • JSON
  • HTML
  • XML
  • pdf 以及More CORB-protected MIME types - adding protected types one-by-one

浏览器判断响应类型: 浏览器拥有Content_sniffing的功能, 会尝试判断响应类型, 并不依赖Content-Type;除非响应头指定 “X-Content-Type-Options: nosniff”, 此时浏览器会直接根据Content-Type的格式进行处理;

例如:

一个 img 标签, 请求一个 html 的数据

  • 响应体 Body: 是一个 HTML document
  • Content-Type: text/html
  • No X-Content-Type-Options header

此时, 浏览器尝试判断响应内容, 如果发现是 html 标签. 则触发 CORB-protected

JSONP 与 CORB
JSONP 算是一种讨巧的跨域请求方式。JSONP 和 CORB 有什么关系呢

在某些情况下, JSONP 会触发 CORB

例如:

响应体 Body: 是 js 代码
Content-Type: text/html
X-Content-Type-Options: ‘nosniff’
通过 script 标签, 获取到 html 的内容(因为指定了 nosniff, 浏览器会直接认为响应内容是 text/html). 从而会触发 CORB, 响应会被清空;

如果服务器发送响应头 “X-Content-Type-Options: nosniff”,则script和styleSheet元素会拒绝包含错误的 MIME 类型的响应。这是一种安全功能,有助于防止基于 MIME 类型混淆的***。

简单理解为:通过设置"X-Content-Type-Options: nosniff"响应标头,对script和styleSheet在执行是通过MIME 类型来过滤掉不安全的文件

服务器发送含有[“X-Content-Type-Options: nosniff”](http://go.microsoft.com/fwlink/p/LinkId=215108 ““X-Content-Type-Options: nosniff””)标头的响应时,此更改会影响浏览器的行为。

如果通过styleSheet参考检索到的响应中接收到 “nosniff” 指令,则 Windows Internet Explorer 不会加载“stylesheet”文件,除非 MIME 类型匹配 “text/css”。

如果通过script参考检索到的响应中接收到 “nosniff” 指令,则 Internet Explorer 不会加载“script”文件,除非 MIME 类型匹配以下值之一:

  • “application/ecmascript”

  • “application/javascript”

  • “application/x-javascript”

  • “text/ecmascript”

  • “text/javascript”

  • “text/jscript”

  • “text/x-javascript”

  • “text/vbs”

  • “text/vbscript”

JSON、JSONP与CORB

JSON是一种数据交换格式,而JSONP是一种非官方跨域数据交互协议。

JSON是一种基于文本的数据交换方式,或者叫做数据描述格式。

JSON的格式或者叫规则:

JSON能够以非常简单的方式来描述数据结构。

1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符。

2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。

3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。

4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号"",以便于不同语言的解析。

5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。

什么是JSONP?

JSONP的产生:

1、Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

2、不过,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如

3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

4、恰巧JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

JSONP的客户端具体实现:

1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

alert('我是远程文件');

本地服务器localserver.com下有个jsonp.html页面代码如下:




    
    





运行结果,页面将会弹出一个提示窗体,显示跨域调用成功。

2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

jsonp.html页面代码如下:




    
    
    





remote.js文件代码如下:

localHandler({"result":"我是远程js带来的数据"});

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据,即{“result”:“我是远程js带来的数据”},这里显示的是“我是远程js带来的数据”,因为是data.result。

跨域远程获取数据的目的基本实现了,但是又一个问题出现了,怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?

3、只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

看jsonp.html页面的代码:




    
    





这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分。调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({           //flightHandler是callback传递的值
    "code": "CA1998",     //这是code传递的值
    "price": 1780,        //这是跨域服务器查询的结果
    "tickets": 5          //这也是跨域服务器查询的结果
});

传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

4、到这里为止,jsonp的客户端实现原理就完成了,剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。

我们这里学习的是jQuery,那么jQuery如何实现jsonp调用?

jQuery使用jsonp的代码


 
 
     Untitled Page
      
      
     
  
  
 

这次没有写flightHandler这个函数也能成功,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时自动帮你生成回调函数并把数据取出来供success属性方法来调用。

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加

3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!

以上来源随它去吧——【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例 - 随它去吧 - 博客园

=======================================

你可能感兴趣的:(面试,学习路线,阿里巴巴,java,java进阶,后端)