《JSON必知必会》- 学习笔记
JSON(读音:Jei森) - JavaScipt Object Notation
JSON概述
什么是JSON: JSON是一种数据交换格式 (实现在不同系统之间的数据交换)
数据交换格式(Data exchange format)是一种在不同平台之间传递数据的文本格式。
可移植性(以一种双方都兼容的方式在平台之间传递信息)在平台和系统之间传输信息的兼容性,是一种数据交换格式的重要指标
In JSON, keys must be strings, written with double quotes. eg:
JSON语法
JSON基于JS对象字面量(字面量是对数据值的具体表示。其字面意思与想要表达的意思是完全一致的 -> 字面量只是表达字面意思而非任何隐喻的内容)
实例: 描述一个学生信息
{
"id" : 1,
"name" : "Wangzhaung2",
"age" : 21,
"school" : "a Nuist student",
"isRich" : false
}
一个对象的字面量直接以一种可以直接可见的方式展现出来。 对象的特征或属性所采用的表示方法: 名称(Key) - 值(Value)对
JSON是基于JavaScript对象字面量的而数据交换格式的核心是: 数据-Data
Key-Type: 字符串类型
Value-Type: 数字、布尔值、数组、对象、null等其他数据类型
{} ->
读取对象[] ->
读取数组 : ->
名称-值对中分割Key和Value , ->
指分割对象中的名称-值对或分割数组中的值
★★★ JSON的双引号 在JSON之中无论如何都使用双引号
Eg: ❌错误1:没有将Key加上双引号
{
title : "This is my title.", // ---> 改正 "title" : "This is my title." ✔
body : "This is the body." // ---> 改正 "body" : "This is the body." ✔
}
===》未在"title"和"body"的两边加上双引号。 没有在名称上加上双引号时该值不是JSON而是JS对象
Eg: ❌错误2:在JSON中只会出现双引号【""】而不会出现单引号【''】(在JS中允许一个对象使用单双引号)
{
'title' : 'This is my title.', // ---> 改正 "title" : "This is my title." ✔
'body' : 'This is the body.' // ---> 改正 "body" : "This is the body." ✔
}
- JSON文件: JSON作为数据转换格式可以作为独立的文件存在文件系统中,扩展名
*.json
- JSON媒体类型: JSON的MIME类型是
application/json
小结
-
字面量: 字面意思与实际表达意思一致,直接表述某一对象的直接特征。
-
键值对:拥有名称和对应的值的属性或特征(Key-Value)
-
JSON中的key ---> 必须是被双引号包裹,eg: {"key":xx}
-
JSON中的value ---> 可以是:
字符串、数字、布尔值、null、对象、数组
-
JSON的 key:value由
{}
包裹 -
JSON文件的扩展名:
*.json
多媒体类型:application/json
-
JSON中的布尔类型只存在:
true 或 false且所有字母必须是小写
JSON Schema
JSON Schema使用JSON来书写,仅需要几步就可以掌握。需要在JSON第一个名称-值对中,声明其为一个schema文件
在第一 key-value声明当前是schema文件
{
"$schema" : "http://json-schema.org/draft-04/schema#"
}
在第二 key-value是JSON Schema的文件标题
{
"$schema" : "http://json-schema.org/draf-04/schema#",
"title" : cat
}
在第三 key-value定义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."
}
定义必填字段
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : cat,
"properties" : {
"name":{"type":"string"},
"age":{"type":"number", "description":"Your cat's age in years."},
"required":["name","age"]
}
在将"required"字段加入JSON Schema后,合法的JSOn包含了在Schema中定义的"name"、"age"两个个字段包含可选字段description
JSON Schema数据交换中的一种虚拟的合同“contract”
JSON的安全问题
JSON本身只提供数据交换的方式并不会造成安全问题(是一种数据文件、数据流)但在Web中使用JSOn时最常见的两个问题: 跨站请求伪造 和 跨站脚本攻击
跨站请求伪造 - CSRF(Cross-site request forgery)
跨站请求伪造即CSRF(Cross-site request forgery)是一种利用站点对用户浏览器信任而发起攻击的方式。
将数组放在对象之中,使其成为非法的JavaScript,这样就不会被
<script>
标签加载
{
"info" : [
{"user" : "bobbarker"},
{"phone" : "xxx-xxx-xxx"}
]
}
服务器只提供POST请求获取数据,禁止使用GET请求,此时将无法使用黑客的URL中伪造连接。GET和POST是HTTP提供的用于与服务器交换数据的安陵中方法
GET 用于请求数据得到响应。
POST 用于提交数据得到响应。
如果服务器端允许GET请求,就可以直接通过浏览器或<script>
标签连接到该服务器资源,但POST不可以被直接链接到。(无法使用<script>
标签黑客将受到资源共享的限制,无法利用银行对客户端的信任进行任何攻击的行为)
是否使用GET方法请求页面或资源: 该页面是否需要通过URL或
<script>
标签来加载?如果不需要通过URL或<script>
标签获取数据则禁用GET方法。
不在JSON中使用顶级数组,不要贪图使用GET代替POST的遍历
跨站脚本攻击(cross-site scripting, XSS)
跨站脚本攻击是注入攻击的一种。在JSON中常见的安全漏洞是发生在JS从Server中获取一段JSON字符串并将其转化为对象时。
JSON本质是文本,对代表对象的文本进行操作,要将其加载到内存之中,这样才能被操作、观察并在程序逻辑中使用。
在JS中可以使用eval()
函数来实现对数据的操作
var jsonString = '{"animal" : "cat"}';
var myObject = eval("(" + jsonString + ")");
alert(myObject.animal);
JSON从别的服务器上获取则己方无权控制第三方服务器,如果服务器本身或发来的JSON数据被劫持则可能会运行恶意代码
eval()
函数的问题: 将传入的字符串无差别的编译执行。
Eg: 使用JS代码来替换原来的JSON字符串。当代码执行时,eval()
函数会执行alert()
函数并弹出"this is bad"
var jsonString = "alert('this is bad')";
var myObject = eval("(" + jsonString + ")");
alert(myObject.animal);
JSON.parse()
函数用来处理这一漏洞,只会解析JSON但不会执行任何脚本。
// 使用JSON.parse() 代替 eval()
var jsonString = '{"animal" : "cat"}';
var myObject = JSON.parse(jsonString);
alert(myObject.animal);
安全漏洞: 决策上的失误
Eg: 规矩JSON
{
"message" : "hello,world"
}
Eg: 不规矩JSON
{
"message" : "<div onmouseover=\"alert('gotcha!')\">hover here.</div>"
}
如何阻止此类情况,可以在消息中添加限制要求将消息中的HTML进行转码 这样
<div>
标签将被转换为<div>
然后插入页面中
★★★ 注入攻击之所以会成功,在于网站在架构过程中忽视了一个问题: 允许在JSON中使用或直接将值插入页面中的一些决策。
抵御注入攻击的关键是: 找出可能的注入点,并添加一些额外的步骤来加以防范
小结
-
CSRF - 跨站请求伪造: 利用站点对用户浏览器的信息进行的攻击。
-
顶层JSON数组 - 存在于JSON名称-值对之外的位于文档最顶层的JSON数组。(禁止使用)
-
注入攻击: 依赖于将数据注入到Web App以方便而恶意数据执行或编译的攻击。
-
JSON跨站脚本攻击: 使用第三方代码更换为恶意脚本对站点进行一种注入攻击。
-
JSON安全问题:
- 不要使用顶级数组。顶级数组是合法的JS脚本,可以用
<script>
标签连接并使用 - 对不想公开的资源,仅允许使用
HTTP POST
方法请求,而不是GET
方法。GET方法可以通过URL来请求,甚至可以放在<script>
标签之中 - 使用
JSON.parse()
来代替eval()
。eval()
函数传入的字符串编译并执行会让代码易受到攻击。 ✔★仅使用JSON.parse()
来解析JSON数据
- 不要使用顶级数组。顶级数组是合法的JS脚本,可以用
- 安全漏洞通常是由于开发人员没有考虑到 "黑客如何利用这一点“ 这一问题造成的(想他人所想)
JavaScript中的XMLHttpRequest与Web API
JS的
XMLHttpRequest
负责在客户端发起请求
Web API负责在服务端返回响应
客户端 ==》 用餐的人,服务端 ==》厨房
互联网浏览器发送的是对某项资源的请求.
JS中的XMLHttpRequest对象
var myXmlHttpRequest = new XmlHttpRequest(); // 创建XmlHttpRequest对象
XMLHttpRequest中以下可用的函数:
-
open(method, url, async(可选), user(可选), password(可选)
-
send()
-
onreadystatechange // 可以在代码中赋值为一个函数
-
readyState // 返回一个0~4的值,用来表示状态码
-
status // 返回HTTP状态码(eg: 200表示请求成功)
- responseText // 当请求成功时,该属性会包含作为文本的响应体(eg: 请求的JSON)
属性的值可以是一个函数。JS中的函数本身也是一个对象。对象这一类数据可以被赋值给一个变量(属性)、修改和传递。
===》 一个新的XMLHttpRequest对象
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文本,或是将JSON文本转成对象时 ===》 序列化和反序列化。
序列化: 将对象转成JSON文本的过程
反序列化: 将文本转换成对象的过程
-
反序列化: 将文本转换成对象
var myObject = JSON.parse(myXMLHttpRequest.responseText);
-
序列化:将对象转换成文本
var myJSON = JSON.stringify(myObject);
就绪状态0-4的含义
DESC | URL |
---|---|
0表示未发送 | 表示open()函数还没有执行 |
1表示已发送 | 表示open()函数已执行,但send()函数还没有执行 |
2表示接收到头部 | 表示send()函数已执行且头部和状态码还没有获取 |
3表示解析中 | 表示头部已经收到,但响应体正在解析中 |
4表示完成 | 表示请求完成,包括响应头和响应体的内容都已经接收到 |
小结
-
Web API 通过HTTP与服务进行交互的一系列指令与标准
-
XMLHttpRequest 一种JS对象,无需刷新页面即可从要给URL中获取数据,常用于AJAX 编程
-
HTTP 作为万维网使用的交换数据的基本协议
-
序列化: 将对象转换为文本 反序列化: 将文本转换成对象
-
同源策略: 出于安全的考虑,浏览器仅会请求同一个域的脚本
-
跨域资源共享(CORS): 通过设置响应头,使得跨域请求资源(eg: JSON doc)可以成功
-
JSON-P:使用
<script>
标签, 绕过同源策略的限制,以从不同域名的服务器上请求JSON -
网站为人服务,Web API为代码服务均使用HTTP协议