本篇文章是阅读《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 | [ |
正确的做法:
1 | { |
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>转成<div>等
抵御注入攻击的关键:找出可能的注入点,并加入一些额外的步骤来加以防范。
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 | var myXMLHttpRequest = new XMLHttpRequest(); |
序列化:将对象转换成文本的过程。 反序列化:将文本转换成对象的过程
序列化: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 | getTheAnimal( |
内联于JSON文档的JavaScript调用了一个函数,函数参数是JSON。函数参数提供了一个将数据传递给函数的方式。