博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
回头再说:jQuery跨域原理
阅读量:5935 次
发布时间:2019-06-19

本文共 4835 字,大约阅读时间需要 16 分钟。

这篇文章作者给出了使用jQuery中的getJSON方法实现跨域的方法;示例代码没有问题,但是作者把getJSON跨域的原理解释成:

 "因为getJSON跨域的原理是把?随机变一个方法名,然后返回执行的,实现跨域响应的目的。"

 这个未免草率了一些,是这么回事么?Firebug里面监控的结果貌似也是这么意思,本文试图探究jQuery getJson跨域的原理;

 

盐从哪儿咸:为什么有跨域的问题

      跨域问题存在实际上源于浏览器的同源策略(),简单讲,同源就是要求域名,协议,端口三者都一致;而同源策略就是指页面上的脚本不能访问非同源的资源(包括HTTP响应和Cookie);上面给出了维基百科的地址,如果无法正常访问请移步这里:

    很多人会想到一个很熟悉的东西:document.domain

    同源策略有点放松的就是:上的页面无法通过的同源验证,但是设置页面的document.domain属性为,就可以通过浏览器对的同源检测;但是,document.domain只允许设置成更上级的域名,而不是其它域名,例如就不行; 提到这里很多人都会想到多级域名下共享Cookie的路子就是把Cooki设置成上级域名;在Web2.0的时代,这种本质上同域跨级解决方案远远不能满足我们跨域的需求;

 

jQuery的解决方案

     浏览器会进行同源检查,这导致了跨域问题,然而这个跨域检查还有一个例外那就是HTML的<Script>标记;我们经常使用<Script>的src属性,脚本静态资源放在独立域名下或者来自其它站点的时候这里是一个url;这个url响应的结果可以有很多种,比如JSON,返回的Json值成为<Script>标签的src属性值.这种属性值变化并不会引起页面的影响.按照惯例,浏览器在URL的查询字符串中提供一个参数,这个参数将作为结果的前缀一起返回到浏览器;

看下面的例子:

 
 
<
script type
=
"
text/javascript
"
src
=
"
http://domain2.com/getjson?jsonp=parseResponse
"
>
<
/
script>
响应值:parseResponse({
"
Name
"
:
"
Cheeso
"
,
"
Rank
"
:
7
})
这种方式被称作;(如果链接已经失效请点击这里:);即:JSON with padding 上面提到的前缀就是所谓的“padding”。那么jQuery里面是怎么实现的呢?
ContractedBlock.gif
后续补充(来自Mx1700)

 

貌似并没有<Script>标记的出现!?OKay,翻看源码来看:

 
1
页面调用的是getJSON:
2
3
getJSON:
function
( url, data, callback ) {
4
return
jQuery.get(url, data, callback,
"
json
"
);
5
},
6
7
8
继续跟进
9
10
get:
function
( url, data, callback, type ) {
11
//
shift arguments if data argument was omited
12
 
if
( jQuery.isFunction( data ) ) {
13
type
=
type
||
callback;
14
callback
=
data;
15
data
=
null
;
16
}
17
18
return
jQuery.ajax({
19
type:
"
GET
"
,
20
url: url,
21
data: data,
22
success: callback,
23
dataType: type
24
});
25
26
 

跟进jQuery.ajax,下面是ajax方法的代码片段:

 
1
//
Build temporary JSONP function
2
 
if
( s.dataType
===
"
json
"
&&
(s.data
&&
jsre.test(s.data)
||
jsre.test(s.url)) ) {
3
jsonp
=
s.jsonpCallback
||
(
"
jsonp
"
+
jsc
++
);
4
5
//
Replace the =? sequence both in the query string and the data
6
 
if
( s.data ) {
7
s.data
=
(s.data
+
""
).replace(jsre,
"
=
"
+
jsonp
+
"
$1
"
);
8
}
9
10
s.url
=
s.url.replace(jsre,
"
=
"
+
jsonp
+
"
$1
"
);
11
12
//
We need to make sure
13
 
//
that a JSONP style response is executed properly
14
 
s.dataType
=
"
script
"
;
15
16
//
Handle JSONP-style loading
17
 
window[ jsonp ]
=
window[ jsonp ]
||
function
( tmp ) {
18
data
=
tmp;
19
success();
20
complete();
21
//
Garbage collect
22
 
window[ jsonp ]
=
undefined;
23
24
try
{
25
delete
window[ jsonp ];
26
}
catch
(e) {}
27
28
if
( head ) {
29
head.removeChild( script );
30
}
31
};
32
}
33
34
if
( s.dataType
===
"
script
"
&&
s.cache
===
null
) {
35
s.cache
=
false
;
36
}
37
38
if
( s.cache
===
false
&&
type
===
"
GET
"
) {
39
var
ts
=
now();
40
41
//
try replacing _= if it is there
42
 
var
ret
=
s.url.replace(rts,
"
$1_=
"
+
ts
+
"
$2
"
);
43
44
//
if nothing was replaced, add timestamp to the end
45
 
s.url
=
ret
+
((ret
===
s.url)
?
(rquery.test(s.url)
?
"
&
"
:
"
?
"
)
+
"
_=
"
+
ts :
""
);
46
}
47
48
//
If data is available, append data to url for get requests
49
 
if
( s.data
&&
type
===
"
GET
"
) {
50
s.url
+=
(rquery.test(s.url)
?
"
&
"
:
"
?
"
)
+
s.data;
51
}
52
53
//
Watch for a new set of requests
54
 
if
( s.global
&&
!
jQuery.active
++
) {
55
jQuery.event.trigger(
"
ajaxStart
"
);
56
}
57
58
//
Matches an absolute URL, and saves the domain
59
 
var
parts
=
rurl.exec( s.url ),
60
remote
=
parts
&&
(parts[
1
]
&&
parts[
1
]
!==
location.protocol
||
parts[
2
]
!==
location.host);
61
62
//
If we're requesting a remote document
63
 
//
and trying to load JSON or Script with a GET
64
 
if
( s.dataType
===
"
script
"
&&
type
===
"
GET
"
&&
remote ) {
65
var
head
=
document.getElementsByTagName(
"
head
"
)[
0
]
||
document.documentElement;
66
var
script
=
document.createElement(
"
script
"
);
67
script.src
=
s.url;
68
if
( s.scriptCharset ) {
69
script.charset
=
s.scriptCharset;
70
}
71
72
//
Handle Script loading
73
 
if
(
!
jsonp ) {
74
var
done
=
false
;
75
76
//
Attach handlers for all browsers
77
 
script.onload
=
script.onreadystatechange
=
function
() {
78
if
(
!
done
&&
(
!
this
.readyState
||
79
this
.readyState
===
"
loaded
"
||
this
.readyState
===
"
complete
"
) ) {
80
done
=
true
;
81
success();
82
complete();
83
84
//
Handle memory leak in IE
85
 
script.onload
=
script.onreadystatechange
=
null
;
86
if
( head
&&
script.parentNode ) {
87
head.removeChild( script );
88
}
89
}
90
};
91
}
92
93
//
Use insertBefore instead of appendChild to circumvent an IE6 bug.
94
 
//
This arises when a base node is used (#2709 and #4378).
95
 
head.insertBefore( script, head.firstChild );
96
97
//
We handle everything using the script element injection
98
 
return
undefined;
99
}
100
 
 上面的代码第1行到第10行:判断是JSON类型调用,为本次调用创建临时的JsonP方法,并且添加了一个随机数字,这个数字源于用日期值; 
这个地方也就是Taven.李锡远所说的“随机变一个方法名”;
关注第14行,这一行相当关键,注定了我们的结果最终是

 

不仅仅是jQuery,很多js框架都是用了同样的跨域方案,:)说到这里,嗯,这就是getJSON跨域的原理,赵本山说了“情况呢就是这么个情况”

 

 

总结

   昨天刚刚和大家探讨过,不要停留在现象,今天这个算是理论照向实践吧;如果还有问题,欢迎拍砖,欢迎

真正勇气不是别人说你有病的时候你回一句:“你丫才有病呢”,而是真诚的问一句“你有药啊”;各位,谁有药啊

 

本文姊妹篇:

转载地址:http://tzntx.baihongyu.com/

你可能感兴趣的文章
运营商的“大网”怎么建? 三大运营商纷纷SDN/NFV三步走
查看>>
通辽智慧城市建设总体规划和顶层设计专家评审会召开
查看>>
未来营销闯关标配:大数据+智能硬件
查看>>
互动性可视化,打通大数据最后一公里
查看>>
为什么媒体如此惧怕 Facebook?
查看>>
我眼中的性能测试工程师
查看>>
台积电与ARM合作开发7纳米芯片 或用于iPhone 8
查看>>
大数据窥探:关于大数据的15条干货思考
查看>>
随谈10年的技术生涯和技术成长
查看>>
《交互式程序设计 第2版》一1.1 本书读者对象
查看>>
各省光伏十三五规划汇总:总规模将超130GW
查看>>
《大数据时代》作者:当下数据隐私保护方式是完全错误的
查看>>
光伏亟待资本注入 业界呼吁第三方“风险评级”
查看>>
2016年网络安全的五大发展趋势
查看>>
郑州成立中原大数据产业联盟
查看>>
MySQL命令行导出数据库
查看>>
“想哭”之余的追问 IEEE数名专家多角度剖析勒索病毒事件
查看>>
Mozilla计划让Firefox浏览器支持WebKit前缀网站
查看>>
VR 的负面效应有那些?其实专家们也不太清楚
查看>>
《实施Cisco统一通信管理器(CIPT2)》一1.9 参考
查看>>