一、同源策略
javascript浏览器使用的同源策略:协议、域名、端口一致,才可以使用ajax直接请求。可以防止CSRF攻击(跨站请求伪造)。
- 使用ajax的时候受到跨域影响。
- 调用js文件的时候,不会受到跨域的影响
- 凡是拥有"src"属性的标签都拥有跨域能力,比如
<script>
,<img>
,<link>
标签ref
属性
解决同源策略:跨域。
- jsonp跨域
跨域的方法有很多种,最经典的就是jsonp跨域。也就是利用上面所说的调用js不受同源策略影响,在web端调用跨域服务器上生成的js格式文件。 - 服务端修改(CORS)
比如在服务端页面添加header限制:
header(‘Access-Control-Allow-Origin:*’); //允许所有来源访问
header('Access-Control-Allow-Origin: https://www.example.com‘);允许https://www.example.com请求
header(‘Access-Control-Allow-Method:POST,GET’); // 允许访问的方式 document.domain
降域
例如http://a.justfun.me
和http://b.justfun.me
,后面的justfun.me
相同,那么就可以使用document.domain
将二者的域名设置为justfun.me
,来实现同源window.postMessage()
HTML5中的API,用于两个窗口之间(主要事父子页面,比如iframe)发送数据信息,是在两个客户端之间的通信。
postMessage(data, url)
// 发送
onmessage
// 监听
二、JSONP
jsonp
是非官方的跨域数据交互协议,动态的创建script
实现。
jsonp实现模式:json数据和callback回调函数。
创建一个回调函数,将他传递给服务端,然后在远程服务上调用这个函数并且将json数据形式作为参数传递回来,完成回调。
jsonp.html页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
remote.js文件:
localHandler({"result":"我是远程js带来的数据"});
这样子就实现了在jsonp.html页面调用了跨域的remote.js文件,获取了文件里的远程数据。
但是jsonp的更多是使用在动态调用远程文件上,实现模式如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
在调用url中传递了一个code参数告诉服务器要查询的航班信息,callback参数则告诉服务区本地的回调函数是flightHandler,让服务器将查询结果传入这个函数中执行。
ajax和jsonp都是从服务端获取数据的方式,那么他们有什么不同之处:
- ajax请求受同源策略影响不能跨域请求,jsonp是跨域请求上的应用
- ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加。
相同:都是请求一个url,然后把服务器返回的数据进行处理。
jsonp缺点:
a. 只支持get方法
b. JSONP可能有CSRF和XSS的安全问题
三、JSON
json语法是javascript对象表示语法的子集。json值可以是数字、字符串(在双引号中),布尔值,数组(中括号),对象(大括号),null
语法规则:
- 数据存储在键/值对中
- 数据由逗号分隔
- 大括号保存对象(用for-in访问)
- 中括号保存数组(用for-in,for访问)
//json对象
{"name": "lian", "age": 18, "flag": true}
//json数组
[ "Google", "Runoob", "Taobao" ]
JSON和XML的相同之处:
- 都是“描述”,易于理解
- 都有“层次结构”
- 可以被大多数编程语言使用
不同之处:
- json不需要结束标签
- json更加简短
- json读写速度更快
- json可以使用数组
方法:
- JSON.parse()
- JSON.stringify()
- eval()
JSON.parse()
JSON数据转换为JS对象,一般用于接收服务器的数据时。
JSON.parse(text[, reviver])
text:必需,json字符串
reviver:可选,转换结果的函数,将对象的每个成员调用函数。
PS:
- 不能存储Date对象 (使用时先将Date转为字符串存储,之后需要的时候再使用
new Data
转为Date对象) - 不能包含函数 (可以先将函数作为字符串存储,之后再用
eval()
转为函数)
var text = '{ "name":"Runoob", "alexa":"function () {return 10000;}", "site":"www.runoob.com"}';
var obj = JSON.parse(text);
obj.alexa = eval("(" + obj.alexa + ")"); //加上括号避免错误
document.getElementById("demo").innerHTML = obj.name + " Alexa 排名:" + obj.alexa();
JSON.stringify()
JS对象转换为JSON数据,一般用于将数据向服务器发送时。
JSON.stringify(value[, replacer[, space]])
value:必需, 要转换的 JavaScript 值(通常为对象或数组)。
replacer:可选。用于转换结果的函数或数组。
space:可选,文本添加缩进、空格和换行符。
如果 replacer 为函数,则 JSON.stringify
将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回
undefined,则排除成员。根对象的键是一个空字符串:""。如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。当 value
参数也为数组时,将忽略 replacer 数组。
PS:
- 不能存储Date对象
- 不能包含函数
JSON.stringify() 会删除 JavaScript 对象的函数,包括 key 和 value。可以在执行 JSON.stringify() 函数前将函数转换为字符串来避免以上问题的发生
eval()
eval()函数可用于计算某个字符串,并执行其中的js代码。
eval(string)
JSON.parse() 和 eval() 的区别
- eval() 不检查所给的字符串是否符合JSON模式
- eval() 会执行字符串中的JS代码(有一定的危险)