json start

json start

json 是什么

json 是一种数据交换格式。

(数据交换格式是一种在不同平台间传递数据的文本格式。)

  1. json 独立于编程语言
  2. 全称是JavaScript Object Notation<span style="color:#be2532">(JavaScript 对象表示法)</span>
    • 关于这个名称,很容易造成误解,虽然 json 源于 JavaScript ,但是 json 是通用的数据交换格式,可以用在不同的系统,不同的语言中。
    • <span style="color:#be2532">json 是源于 JavaScript 字面量的。</span>
    • 所以,我们可以这么理解 json :<u>一种<span style="color:#be2532">基于对象表示法的数据交换格式</span></u>
      • 对象,是面向对象编程中很常见的概念。
      • 而不太容易理解的是表示法,<span style="color:#be2532"><u>表示法是指一个可以表示如数字或单词等数据的字符系统</u>。</span>
  3. json 之所以流行,是因为其不仅独立于语言,而且使用了一种在许多编程语言中都能找到共同元素的表达方式。
    • 通过这种表达数据的方式,即便是那 些不支持面向对象编程的语言,也会发现 json 这种格式是可以接受的。

json的文件,媒体类型

  1. json 文件的后缀就是.json
  2. json 的媒体类型(MIME)为application/json

json 语法

示例

json 所基于的 JavaScript 对象字面量单纯指对象字面量及其属性的语法表示,而且<u>这种属性表示方法也就是通过名称 - 值对来实现的。</u>

<span style="color:#be2532">json 的最外层为花括号{ },表示一个对象,而括号里面,都是由被称为名称-值对(键值对)组成。</span>

{
    "animal":"horse"
}

上面这个就是最简单的一段 json 数据。

正确的 json 语法

  1. 先来看看:名称-值对中的名称
    在,json 中名称即上面的"animal",必须
    1. 双引号包裹
    2. 而且是有效的字符串
      • 最好是英文字母 A~Z 或 a~z。
  2. 多个名称-值对用逗号隔开

json 的数据类型

上面说了,<span style="color:#be2532">名称-值对中的<u>名称为双引号包裹的字符串</u></span>,而 json 的数据类型指的是值对的数据类型。
包括:

1. 对象  
    - 对象可以嵌套  
2. 字符串
    - 可能需要用`\`转义  
3. 数字   
    - 整数、小数、负数或者指数  
4. 布尔值   
    - 格式非常严格,只能使用小写的 true,false
5. null   
    - 表示没有值,必须为小写的 null  
6. 数组   
    - []包裹,值之间用逗号隔开

json 中的字符类型

重点要说的是字符串类型,在 JavaScript 中,使用单引号或双引号没有任何区别,但是 <span style="color:#be2532"><u>json 只是基于 JavaScript 对象字面量</u>。 而<u>在 json 中,仅允许使用双引号来包裹字符串。</u></span>

另外,<u>json 中的字符串还涉及到一个转义的问题</u>,即解析器在解析 json 时,当读到一个双引号 “ 时,就认为接下来是一个字符串文本,并且预期有另一个双引号 “ 结尾,这就意味着,如果这段字符串本身含有双引号,那么就有可能会解析错误。

为了处理这个问题,我们需要 <u>在字符串中的双引号前面加上一个反斜线字符来对其转义</u>。

另外还有其他一些需要转义的字符:

• \\(反斜线)  
• \/(正斜线)  
• \(退格符)  
• \(换页符)  
• \(制表符)  
• \(换行符)  
• \(回车符)  
• \u后面跟十六进制字符(如笑脸表情\u263A) 
  • json 中的数字可以是`整数、小数、负数或者指数。

  • json 中的布尔类型非常严格,<u>仅使用小写形式:true 或 false,任何其他 形式的写法都会报错。</u>

  • json 中的null类型,编程中当我们需要表示没有,不存在,空,一无所有等等意思的时候,我们不用数字0表示,而是 null ,null 是一个表示“没有值”的值。在 json 中,<u>null 必须使用小写形式。</u>

  • json 中同一个数组里,可以放置不同类型的数据,但是尽量避免这么做,数组里的值类型可以包括:<u>字符串、数字、布尔值、对象 或数组中的任何一种</u>,数组必须被方括号[]包裹,且值与值之间用 逗号隔开。

json 数据的一致性验证

发送方和接收方都可以使用 json Schema 来校验数据。

  1. 对于发送方来说,在发送数据前,随时可以验证数据是否与 Schema 一致,以便知道会不会被接收方接受。如果出现错误,也可以轻松定位和修复。
  2. 对于接收方来说,可以将 json Schema 放在接收数据的第一行,以保证数据符合要求。主要在数据被处理前回答三个问题。
  • 2.1 <span style="color:#be2532"><u>值的数据类型是否正确?</u></span>
    • 可以具体规定一个值是数字、字符串等类型。
  • 2.2 <span style="color:#be2532"><u>是否包含所需要的数据?</u></span>
    • 可以具体规定哪些数据是需要的,哪些是不需要的。
  • 2.3 <span style="color:#be2532"><u>值的形式是不是我需要的?</u></span>
    • 可以指定范围、最小值和最大值。

json Schema

<span style="color:#be2532">json Schema 也是使用 json 来书写。</span>

一、第一个名称 - 值对中,声明其为一个 schema 文件。声明的名称必须为 “$schema”,值必须为所用草拟版本的链接。

二、 第二个名称 - 值对应该是 json Schema 文件的标题。

{
    "$schema": "http://json-schema.org/draft-04/schema#",  
    "title": "Cat" 
}

三、 第三个名称值对中,要定义需要在json中包含的 属性。例如定义猫的属性。

{  
    "$schema": "http://json-schema.org/draft-04/schema#",  
    "title": "Cat",  
    "properties": {  
        "name": {  
            "type": "string"  
        },  
        "age": {  
            "type": "number",  
            "description": "Your cat's age in years."  
        },  
        "declawed": {  
            "type": "boolean"  
        }  
    }   
} 

在第三个名称 - 值对中,我们验证了第一个问题,<u>值的类型是否正确。</u>
如果需要验证第二个问题–<u>是否包含所需要的数据。</u>就需要第四个名称 - 值对。

四、 第四个名称 - 值对,<u>名称为 “require”,值为数组,数组中包含必填的字段</u>。

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Cat",
    "properties": {
        "name": {
            "type": "string"
        }, 
        "age": {
            "type": "number",
            "description": "Your cat's age in years."
        },
        "declawed": {
            "type": "boolean"
        },
        "description": {
            "type": "string"
        }
    },
    "require": [
        "name",
        "age",
        "declawed"
    ]
}

下面是一个合法的 json:

{
    "name": "Fluffy",
    "age": 2,
    "declawed": false,
}

注:
如果你的 json Schema 中<u>不包含 “require” 名称-值对,那么将不会有必填项。</u>

下面解决第三个问题:值的形式是不是我需要的?

这个可以通过<span style="color:#be2532"><u>对数据的格式提出更具体的要求来实现</u></span>,比如设置数字的最大、最小值,字符串长度的最长最短等等。

下面是示例:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Cat",
    "properties": {
        "name": {
            "type": "string",
            "minLength": 3,
            "maxLength" : 20
        },
        "age": {
            "type": "number",
            "description": "Your cat's age in years.",
            "minimum" : 0
        },
        "declawed": {
            "type": "boolean"
        },
        "description": {
            "type": "string"
        }
    },
    "requi#be2532": [
    "name",
    "age",
    "declawed"
    ]
}

json Schema 同时还支持正则表达式和枚举类型

  • 正则表达式
    • 一种字符形式
  • 枚举类型
    • 一个 包含所有可能值的列表

json 中的安全问题

json 本身并不会造成什么安全问题,可能会出现问题的是 json 的使用。
主要是两点:

  1. <span style="color:#be2532"><u>跨站请求</u></span>
  2. <span style="color:#be2532"><u>跨站脚本攻击</u></span>

跨站请求伪造

跨站请求伪造,即 CSRF(cross-site request forgery,读作 sea-surf),是一种 <span style="color:#be2532"><u>利用站点对用户浏览器信任而发起攻击的方式。</u></span>

那 json 和 CSRF 攻击又有什么联系呢?

下面这个看上去不像 json 的 json 数据<u>被称为<span style="color:#be2532">顶层 json 数组</span>,是<span style="color:#be2532">可以作为被执行的 JavaScript 脚本。</span></u>

[
    {
        "user": "bobbarker"
},
    {
        "phone": "555-555-5555"
    }
]

因为浏览器对于跨域名的资源共享有一定的限制,所以,黑客通常使用 <script> 标签来绕开这些规则(<script>可以引用其他站点的脚本),<span style="color:#be2532">使用顶层级别数组的 json 是合法的 JavaScript 代码</span>

那如何防范这种跨站请求伪造呢?

一、 首先<span style="color:#be2532">不在 json 中使用顶级数组,应该将数组作为一个值存入 json 对象。这样的数组将不再是合法的 JavaScript。</span>

{
    "info": [
        {
            "user": "bobbarker"
        },
        {
            "phone": "555-555-5555"
        }
    ]
}

二、网站,<span style="color:#be2532">应仅允许 POST 请求获取数据,禁止使用 GET 请求</span>

注入攻击

CSRF(跨站请求伪造)攻击仅包括利用信任机制进行的攻击。<span style="color:#be2532">注入攻击则主要通过向网站注入恶意代码</span>来实现。

一、 跨站脚本攻击

跨站脚本攻击(cross-site scripting,XSS)是注入攻击的一种。<u>在使用 json 时常见的安全漏洞通常发生在 JavaScript 从服务器获取到一段 json 字符串并将其转化为 JavaScript 对象时。</u>
要知道,json 本身仅仅是文本。<u>在编程中,<span style="color:#be2532">如果想要对代表对象的文本进行操作,首先要将它转换成对象并装入内存中。</span>这样,它才能被操作、观察,并在程序逻辑中使用。</u>

在 JavaScript 中,可以<span style="color:#be2532">使用 eval() 函数来进行这一操作。该函数<u>获取一段字符串,并对其进行编译与执行</u></span>

示例:

1. var jsonString = '{"animal":"cat"}';   
2. var myObject = eval("(" + jsonString + ")");   
3. alert(myObject.animal);

使用 eval() 函数来将 animal/cat 对象放入内存中。之后就可以在代码中使用该对象的属性了。

代码相对来说没有什么危险,因为 json 是直接位于代码中的。不过在一些情况下,我们的 json 是从别的服务器上获取的。如果服
务器本身或发来的 json 数据被人劫持,那么很可能就会运行恶意代码。
<span style="color:#be2532"><u>eval() 函数的问题是,它会将传入的字符串无差别地编译执行。</u></span>如果从第三方服务器中获取的 json 被替换为了恶意脚本,那么我的站点就会无辜地蒙冤,在访问者的浏览器中编译执行恶意代码。

如果用一些 JavaScript 代码来替换原本的 json 字符串。

1. var jsonString = "alert('this is bad')";   
2. var myObject = eval("(" + jsonString + ")");   
3. alert(myObject.animal); 

执行结果是,直接弹出 this is bad

<span style="color:#be2532">JSON.parse() 函数</span>就是用来处理这一问题的。<u>该函数仅会解析 json,并不会执行脚本。</u>

1. var jsonString = '{"animal":"cat"}';   
2. var myObject = JSON.parse(jsonString);   
3. alert(myObject.animal); 

JSON.parse() 函数更加安全,目前已经被全部主流浏览器的最新版本所支持。

找出可能的注入点")找出可能的注入点

对于一些合法的 json 数据,也可能包含一些危险。

比如 json 中可能包含了 JavaScript 脚本:

{  
    message": "hover here."  
}

这段 JavaScript,当它在网站的消息页面中输出时,就会构成威胁。示例中的这段“不规矩的 json”会在用户每次将鼠标移动至
屏幕上的消息时弹出内容为“gotcha!”的警告框。
当然,如果是黑客攻击,不是简单的弹出一个警告框这么简单了,可能会将你的私人信息发送到他的服务器。

如何阻止这种情况呢?

  • 一方面,<span style="color:#be2532">可以采取一些手段使得消息中不包含 HTML。</span>可以在客户端和服务端都加上这一认证。

  • 此外,<span style="color:#be2532">还可以将消息中所有的HTML字符进行转码,</span>这样的话,诸如 <div> 这样的标签就会被转换成 <div>,然后插入页面(<div> 将不会是合法的 HTML)。

    总之,<u>抵御注入攻击的关键是<span style="color:#be2532">要找出可能的注入点</span>,并加入一些额外的步骤(有时可能会很麻烦)来加以防范。</u>

总结:

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

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

1.  不要使用顶级数组。顶级数组是合法的 JavaScript 脚本,它们可以用  
    <script> 标签链接并使用。
2.  对于不想公开的资源,仅允许使用 HTTP POST 方法请求,而不是 GET  
    方法。GET 方法可以通过 URL 来请求,甚至可以放在 <script> 标签中。
3.  使用 JSON.parse() 来代替 eval()。eval() 函数会将传入的字符串编  
    译并执行,这会让你的代码易被攻击。应仅使用 JSON.parse() 来解析 JSON 数据。

安全漏洞通常是由于开发人员没有考虑“黑客如何利用这一点”这一问
题所造成的。

JavaScript中的 XMLHttpRequest 与 Web API

<u>JavaScript 中的 <span style="color:#be2532">XMLHttpRequest</span> 负责<span style="color:#be2532">在客户端发起请求</span>。而 <span style="color:#be2532">Web API</span> 负责<span style="color:#be2532">在服务端返回响应。</span></u>

Web API

<span style="color:#be2532">Web API 是通过 HTTP 服务进行交互的一组指令和标准。</span>这些交互可以包括创建、读取、更新、删除(CRUD)等操作,且 Web API 都会有一份说明,概述如何使用这些指令和标准。

这里要提到 JavaScript 中的异步(后台)操作– AJAX。AJAX这个专有名词使用的时间已经很久了,很多
时候,与其说它是一个首字母缩写,不如说是用来描述 JavaScript 中的任何一种异步操作。

接下来看看如何用 json 和 JavaScript 中的 XMLHttpRequest 实现 AJAX。

JavaScript中的XMLHttpRequest对象

尽管 JavaScript 的 XMLHttpRequest 对象听上去和 XML 有关,但实际上我们使用它来发起 HTTP 请求。然而,<span style="color:#be2532">XMLHttpRequest 并不仅限于使用 XML。</span>

当使用 new XmlHttpRequest() 语法,并将其返回值赋值给一个变量时,<u>它就具有了从某一地址请求资源的功能。</u>

var myXmlHttpRequest = new XMLHttpRequest();

我们说过,JavaScript对象具有属性。这些“属性”就是名称-值
XMLHttpRequest对象所拥有的属性有 onreadystatechange、readyState、 response、 responseText、 responseType、 responseXML、 status、 statusText、timeout、ontimeout、upload 以及 withCredentials

XMLHttpRequest 中还包含以下这些可用的函数:

*   open(method,url,async(可选),user(可选),password(可选))
*   send()

以及下面这些属性:

*   onreadystatechange  
    可以在代码中给它赋值为一个函数
*   readyState  
    返回一个 0~4 的值,用来表示状态码
*   status  
    返回 HTTP 状态码(如 200 表示请求成功)
*   responseText  
    当请求成功时,该属性会包含作为文本的响应体(如我们请求的 JSON)

属性的值可以是一个函数。因为 JavaScript 中的函数也是一类对象。对象是一类数据,因此它可以被赋值给一个变量(属性)、修改和传递。在编程中,这种情况称为“函数是一等公民”。

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 文本时,涉及到一个序列化和反序列化问题。

  • <span style="color:#be2532">序列化</span>是将<span style="color:#be2532">对象转换成文本的过程</span>
    • 在 JavaScript 中,可以通过 <span style="color:#be2333">JSON.stringify() 对 json 进行序列化。</span>
  • <span style="color:#be2532">反序列化</span>是将<span style="color:#be2532">文本转换成对象的过程。</span>
    • JavaScript 中的 <span style="color:#be2333">JSON.parse() 进行反序列化操作</span>

突破同源策略

然而,出于安全考虑,浏览器对资源共享有一定的限制。同源策略就要求此类后台请求仅可以请求来自同一域名的资源。

跨域资源共享CORS(cross-origin resource sharing)

这是因为这些公共 API 的开发者在他们的服务器上实现了<span style="color:#be2532">跨域资源共享(cross-origin resource sharing,CORS)。</span>这些服务器会在响应头额外加上一些带有 Access-Control-Allow 前缀的属性

1. Access-Control-Allow-Credentials:true
2. Access-Control-Allow-Methods:GET, POST
3. Access-Control-Allow-Origin:*

这些头部定义了证书是否可用,哪些 HTTP 方法(GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECT)是可用的,以及最重要的一点,即允许哪些域名。本例中,此处包含一个星号(*)。它表示任意域名都是允许的。

同时,<span style="color:#be2532">CORS 还可用于禁止某些域名的访问</span>,来防止有些人用 API 做坏事。

1. Access-Control-Allow-Methods:POST  
2. Access-Control-Allow-Origin:http://www.somebank.com

本例中,我们仅允许通过 POST 方式请求资源。如果有人想通过将 URL 放
<script> 标签来进行请求(使用 GET 方式),浏览器会阻止他。同时,由于具体设定了银行站点的 URL,浏览器会禁止除 http://www.somebank.com 以外的站点去获取资源。

JSON-P

JSON-P 指带有 padding 的 JSON。我在第 5 章提到过 <u><script> 标签不受同源策略的影响。JSON-P 就是利用这一点来向不同域名的站点请求 JSON 的。</u> JSON-P 并没有CORS那么理想,它只是一个备选方案(CORS是更好的方案,同时也是一种标准)。不过有些时候,还是很需要这种不是很规范的解决方案的。

getTheAnimal(  
    {  
       "animal": "cat"  
    }  
);

<u>内联于 json 文档的 JavaScript 调用了一个函数,函数参数是 json 。</u>函数参数提供了一种将数据传递给函数的方式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容