JSON笔记

本篇文章是阅读《JSON必知必会》所做的笔记。虽然JSON的内容比较少,但做成记录也是极好的。

JSON是一种数据交换格式。JavaScript Object Notation

JSON独立于编程语言。

JSON需要用双引号包裹key-value。当值是字符串时,必须使用双引号。如果是数字,布尔值,数组,对象,null等其他数据类型,则不应该被双引号包裹。多个key-value之间用逗号来分割。

可以在双引号内部使用单引号,空格等特殊字符(即英文数字以外的其他字符).但这不是一种好的选择,因为使用空格和特殊字符忽略了可移植性。

PS:JSON的key必须用双引号包裹。如果没有双引号,那这并不是一个JSON对象,而是一个JavaScript对象。而且在JavaScript中,可以使用单引号来代替双引号,但JSON必须使用双引号。

在传递数据时,需要提前告知接收方数据是什么类型,这就涉及到媒体类型。(又称,互联网媒体类型,内容类型Content-type,MIME类型)它使用”类型/子类型”这种格式来表示,比如text/html。

JSON的MIME类型是:application/json

JSON的对象数据类型可以嵌套。比如一个JSON可以作为另一个JSON的key-value

\用作转义。

(上面的例子: \n表示换行,而\n就是普通的字符串\n)

JSON的布尔类型只允许小写形式true或false。用1和0,TRUE,FALSE都会报错。

(PS:用1和0不是报错,但这时候变成了数字类型,而不是布尔类型。而用大写的TRUE跟FALSE,True等,则会直接报错)

对于JSON的null属性,也必须是小写。(而且JSON没有undefined,那是JS的)

JSON的数组类型,用[ ]包裹。数组的每一项用逗号隔开,而且,数组里可以是任意合法的JSON数据类型。比如同时具备字符串和数字。[“qqq”, 234, null, “rrr”]

但最好不要这样做,应该使得数组的每一项都是相同的数据类型

(因为在大多数编程语言里,都是如此的。提高可移植性)

JSON Schema:定义JSON数据的数据要求。比如哪些字段是必填的,哪个字段有哪些要求,最大长度为多少,哪个字段必须是什么数据类型等等。

PS:JSON Schema同样需要用双引号包裹。

例子:

这就是一个Schema文件。

在验证JSON的时候,JSON Schema Lint。

一方面输入JSON Schema,一方面输入JSON。

预防网络攻击:

1.JSON中存储的数组,应该放在对象中,使其成为非法的js,否则一个JSON只存储了一个数组,这时候它既是合法的JSON,也是合法的js,进行CSRF攻击则可以运行js,获取JSON里的敏感信息。CSRF,cross-site request forgery,(sea-surf)跨站请求伪造。

例子:不好的做法:(虽然最外面没加花括号,但它是合理的,这称为顶层JSON数组)

1
2
3
4
5
6
7
8
[
{
"user": "bobbarker"
},
{
"phone": "555-555-5555"
}
]

正确的做法:

1
2
3
4
5
6
7
8
9
10
{
"info": [
{
"user": "bobbarker"
},
{
"phone": "555-555-5555"
}
]
}

XSS,cross-site scripting,跨站脚本攻击(注入攻击,通过向网站注入恶意代码来实现)

JSON是一个脚本,要代表对象再进行操作,需要将其转换成对象,并装入内存中。

在JavaScript中,使用eval( )函数可以将文本转换成对象。

当JSON被拦截并修改成恶意代码,用eval函数会直接变成调用JSON的脚本。比如JSON被修改成alert方法,eval方法本该是把JSON文本变成对象,但这里会直接调用了alert方法,即JSON如果被修改成一个脚本,eval方法就会变成执行该脚本。

正确的方法是,使用JSON.parse( )函数来替代eval。该函数仅会解析JSON,而不会执行脚本。所以如果JSON被修改成脚本,该parse就不会通过,报错并且不会执行脚本。

当用户之间的信息传递是用JSON传递的时候,必须要用eval,这个时候就可能出现,JSON里存在脚本,进行注入攻击。

可以使得信息中不能包含HTML,或者把HTML字符转码,比如把<div>转成&lt;div&gt;等

抵御注入攻击的关键:找出可能的注入点,并加入一些额外的步骤来加以防范。

JSON本身不构成什么威胁,它只是文本。

在定位JSON安全问题的时候,应该记住以下三件事。

①不要使用顶级数组。顶级数组是合法的Javascript脚本,它们可以用<script>标签链接并使用。

②对于不想公开的资源,仅允许使用HTTP POST方法请求,而不是GET方法。GET可以通过URL来请求,甚至可以放在<script>标签链接中。

③使用JSON.parse()来代替eval()。eval()函数会将传入的字符串编码并执行,这会使你的代码易被攻击。

尽管Javascript的XMLHttpRequest对象看上去和XML有关,但实际上我们使用它来发起HTTP请求。在它包含XML的名字命名时,XML是在发起这类请求时最常用的数据交换格式。然而XMLHttpRequest并不仅限于使用XML,用于请求JSON是完全可以的。

从Web Api上获取JSON数据:(一个例子)

1
2
3
4
5
6
7
8
9
10
11
var myXMLHttpRequest = new XMLHttpRequest();
var url = "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139";

myXMLHttpRequest.onreadystatechange = function() {
if (myXMLHttpRequest.readyState === 4 && myXMLHttpRequest.status === 200) {
var myObject = JSON.parse(myXMLHttpRequest.responseText);
var myJSON = JSON.stringify(myObject);
}
}
myXMLHttpRequest.open("GET", url, true);
myXMLHttpRequest.send();

序列化:将对象转换成文本的过程。 反序列化:将文本转换成对象的过程

序列化:JSON.stringify( ) 反序列化:JSON.parse( )

浏览器一般对资源共享有限制,只允许来自同一域名的资源。

CORS,cross-origin resource sharing,跨域资源共享。

可以在响应头加上Access-Control-Allow前缀的属性,来控制,哪些HTTP方法可用,哪些域名可用等等。(在对抗CSRF时,设置只允许POST,则避免了CSRF的恶意GET方法。而且设置只允许同一域名可以获取资源,这样可以避免外部获取资源)

CORS,JSON-P

JSONP(JSON with Padding)是资料格式JSON的一种使用模式,可以让网页从别的网域索要资料。由于同源策略,一般来说位于server1.example.com的网页无法与不是server1.example.com的服务器沟通,而HTML的<script>元素是一个例外。利用<script>元素 的这个开放策略,网页可以得到从其他来源动态产生的JSON资料,而这种使用模式就是所谓的JSONP。用JSONP抓到的资料并不是JSON,而是任意的JavaScript,用JavaScript直译器执行而不是用JSON解析器解析。

JSON-P的padding(内联),就是将JavaScript加入JSON文档。如:

1
2
3
4
5
getTheAnimal(
{
"animal": "cat"
}
);

内联于JSON文档的JavaScript调用了一个函数,函数参数是JSON。函数参数提供了一个将数据传递给函数的方式。

-------------本文结束感谢您的阅读-------------