JSON基础与Restful风格接口

1,214 阅读13分钟

我们在写Restful风格接口时,使用JSON交换信息,我们先重新认识JSON

什么是JSON

JSON JavaScript Object Notation

  1. 定义:JavaScript对象表示法
  2. 用途:JSON是轻量级的文本数据交换格式
  3. 特点:
  • JSON使用JS语法来描述数据对象,但是JSON独立于语言和平台,JSON解析器和JSON库支持许多不同的编程语言
  • JSON具有自我描述性,更易理解 JSON是储存和交换文本信息的语法,与XML有相同的功能 但是JSON更小,更快,更易解析

创建JSON

JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。

由于这种相似性,无需解析器,JavaScript 程序能够使用内建的 eval() 函数,用 JSON 数据来生成原生的 JavaScript 对象。

<script>
//创建json对象
var JSONObject= {
    "name":"菜鸟教程",
    "url":"www.runoob.com", 
    "slogan":"学的不仅是技术,更是梦想!"
};
document.getElementById("jname").innerHTML=JSONObject.name 
document.getElementById("jurl").innerHTML=JSONObject.url 
document.getElementById("jslogan").innerHTML=JSONObject.slogan
</script>

JSON的语法

JSON的语法是JS语法的子集

  • 数据在key/value对中
  • 数据由逗号分隔
  • 大括号保存对象
  • 中括号保存数组

本来想调个自己的接口看下,发现周末开发环境mysql down了... 调用了个报错的吧,也是各个元素都有了

{"code":500,"message":"接口 [/employee/account/business/system] 内部错误,请联系管理员"}

大括号保存整个对象,数据用逗号分隔,返回的这是一个封装的异常对象,其中有两个key/value,分别是code和message

JSON的值

JSON 值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

JSON对象(JSONObject)

  1. JSON对象在大括号{}中书写,可以包含多个键值对,key必须是字符串,而value可以是合法的数据类型,如字符串,数字,对象,布尔值,或者NULL;
  2. key和value之间使用冒号: 分隔
  3. 每个k/v之间使用,分隔
{ "name":"菜鸟教程" , "url":"www.runoob.com" }

嵌套JSON对象

即刚才的JSON对象的value中也是一个对象的用法,还是本着{}包对象的原则,给对象加一个大括号即可,如果是一个数组,就加一个中括号即可

myObj = {
    "name":"runoob",
    "alexa":10000,
    "sites": {
        "site1":"www.runoob.com",
        "site2":"m.runoob.com",
        "site3":"c.runoob.com"
    }
}

JSON数组(JSONArray)

JSON数组在中括号中书写,数组可以包含多个JSON中的数组值也得是合法的JSON数据类型,还是那些,字符串,数字,对象,数组,boolean或者NULL

{
"sites": [
{ "name":"菜鸟教程" , "url":"www.runoob.com" }, 
{ "name":"google" , "url":"www.google.com" }, 
{ "name":"微博" , "url":"www.weibo.com" }
]
}

看这一个JSON对象,其中包含了一个叫"sites"的数组,数组中又包含了三个对象,每一条代表了一条记录

对象的属性可以是一个数组

{
"name":"网站",
"num":3,
"sites":[ "Google", "Runoob", "Taobao" ]
}

如这个json,名为sites的数组包含了三个字符串元素

嵌套 JSON 对象中的数组

JSON 对象中数组可以包含另外一个数组,或者另外一个 JSON 对象

myObj = {
    "name":"网站",
    "num":3,
    "sites": [
        { "name":"Google", "info":[ "Android", "Google 搜索", "Google 翻译" ] },
        { "name":"Runoob", "info":[ "菜鸟教程", "菜鸟工具", "菜鸟微信" ] },
        { "name":"Taobao", "info":[ "淘宝", "网购" ] }
    ]
}

JSON 文件

  • JSON 文件的文件类型是 ".json"
  • JSON 文本的 MIME 类型是 "application/json"

最后了解一下JSONP

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

了解完Restful的数据交换格式Json,我们再来聊聊Restful,在移动互联网的大潮下,随着docker等技术的兴起,『微服务』的概念也越来越被大家接受并应用于实践,日益增多的web service逐渐统一于RESTful 架构风格

什么是Restful及其特点

REST即Representational State Transfer的缩写,可译为"表现层状态转化”。REST最大的几个特点为:资源、统一接口、URI和无状态。

特点详解

  1. 资源 所谓资源,就是网络上的一个实体,或者说网络上的一个具体信息,它可以是一段文本,一张图片等,JSON是现在最常用的资源表示格式。

资源是以JSON(Representation)为载体,面向用户的一组数据

  • 资源总是以某种Representation(推荐json)为载体显示的,即序列化的信息
  • Represntation 是REST架构的表现层

用开发的思维去理解的话,我们从DB中取到原始的数据,经过各种处理,形成了资源,通过表现层(Represntation),也就是JSON形成一种资源,供用户调用

  1. 统一接口

RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和delete,即数据的增删查改)操作,分别对应于HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口,仅通过HTTP方法,就可以完成对数据的所有增删查改工作。 即:

GET(SELECT):从服务器取出资源(一项或多项)。

POST(CREATE):在服务器新建一个资源。

PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。

PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。

DELETE(DELETE):从服务器删除资源。

  1. URI 可以用一个URI(统一资源定位符)指向资源,即每个URL对应一个特定的资源,要获取这个资源,访问URI就可以 在Restful中,最典型的URI即URL,我们通过URL去获取资源

URI 是统一资源标识符,而 URL 是统一资源定位符,URL是URI的一个特例,它包含了定位Web资源的足够信息

4.无状态 无状态指的是,所有的资源都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而变化

举个简单的例子说明一下。如查询员工的工资,如果查询工资是需要登录系统,进入查询工资的页面,执行相关操作后,获取工资的多少,则这种情况是有状态的,因为查询工资的每一步操作都依赖于前一步操作,只要前置操作不成功,后续操作就无法执行;

如果输入一个url即可得到指定员工的工资,则这种情况是无状态的,因为获取工资不依赖于其他资源或状态,且这种情况下,员工工资是一个资源,由一个url与之对应,可以通过HTTP中的GET方法得到资源,这是典型的RESTful风格。

ROA,SOA,RPC,Rest

ROA(Resource Oriented Architecture)为面向资源架构,SOA(Service Oriented Architecture)面向服务架构,RPC(Remote Procedure call)远程过程调用

我们之前也分析过Restful架构的特点,即核心是资源,JSON作为资源的表示层(Representation),显示Restful是一种典型的ROA架构

但是说ROA和SOA并不冲突,既然要返回资源,还是得有服务提供资源吧,甚至可以把ROA看做SOA的一种,而RPC也是SOA,万物都是SOA

我们常常把Restful称为ROA,是因为要和RPC区分

本真Rest与Hybrid风格

我们使用的Restful服务分为,本真Rest和Hybrid风格

本真Rest即我们上面说的Restful架构风格,具有资源,统一调用方式(GET,PUT,POST,DELETE),URI,无状态四个特点,是真正意义上的Restful风格

而hybird风格则是借鉴了Restful架构的一些特点,使用GET获取资源,使用POST实现资源的创建,修改和删除... 因此,不建议使用hybird风格

认证

实现很重要,安全更重要,无状态的Restful我们该如何实现认证? 例如前面说的员工工资,是一个隐私资源,应该仅由有权限的人看到,如果不通过权限认证机制对资源做一层限制,公开暴露资源是不合理的

认证机制:确定用户是谁 授权机制:确定用户的CURD权限,因此权限是每个业务系统中定制的

而认证基本是通用的,常用的认证有session auth(即通过用户名密码登录),Restful开发中常用的有basic authtoken authOAuth

如postman中所示,认证方式还是蛮多的

  1. Bath Auth Basic Auth是配合RESTful API 使用的最简单的认证方式,只需提供用户名密码即可,但由于有把用户名密码暴露给第三方客户端的风险,在生产环境下被使用的越来越少。因此,在开发对外开放的RESTful API时,尽量避免采用Basic Auth

  2. Token Auth Token Auth并不常用,它与Basic Auth的区别是,不将用户名和密码发送给服务器做用户认证,而是向服务器发送一个事先在服务器端生成的token来做认证。因此Token Auth要求服务器端要具备一套完整的Token创建和管理机制,该机制的实现会增加大量且非必须的服务器端开发工作,也不见得这套机制足够安全和通用,因此Token Auth用的并不多。

  3. 重点来了 OAuth2.0 即Open Authorization2.0 开放授权2.0 OAuth2.0官网

注意认证 (authentication) 和授权 (authorization)

OAuth2是什么

OAuth 2.0是用于授权的行业标准协议。OAuth 2.0致力于简化客户端开发人员的工作,同时为Web应用程序,桌面应用程序,移动电话和客厅设备提供特定的授权流程。是一种授权协议,不涉及具体的代码,表示一种约定的流程和规范,现在已经成为SSO和用户授权的标准

OAuth2解决了什么问题

任何身份认证,本质上都是基于对请求方的不信任.同时,由于用户是主动发起请求的,所以认为用户信任了服务方,所以,身份认证就是解决身份的可信任问题

在Oauth2.0中,简单来说有4个角色,用户(服务方的用户,指在服务方有账号密码的用户),服务方(微信,github),第三方应用,资源服务器(服务方的资源服务器,拥有用户资源)

  1. 服务方不信任用户,所以需要用户提供账号密码/扫二维码
  2. 服务方不信任第三方应用,所以需要第三方提供自己交给它的凭据(如授权码)
  3. 用户部分信任第三方应用,所以用户愿意把在服务方中的资源服务器中的某些内容交给第三方,但是不愿意直接交给第三方应用用户名密码

参考,讲的太好了 理解OAuth2.0认证与客户端授权码模式详解

区别于Base Auth,比如我们想授权给postman(第三方应用)去访问我们的接口,如果是基于BaseAuth,那么我们得把用户名/密码交给postman(第三方应用)

那么OAuth2.0最核心解决的问题就是,当我们需要给第三方授权时,第三方并不会接触到我们的用户名密码,也不用用户名密码去申请用户资源的授权(使用token),因此Oauth2.0是安全的

OAuth2.0的一般步骤

  1. 掘金(第三方应用)登录,采用微信登录的方式,要求用户给授权
  2. 用户同意授权(微信是进行扫描二维码的方式,github是跳转到github认证中心,进行账号密码登录,完成授权)
  3. 根据上一步的认证中心的授权(返回授权码),第三方向认证中心请求令牌(token)
  4. 认证中心对授权进行认证,确认无误后返回令牌(token)
  5. 第三方使用令牌向资源服务器请求资源
  6. 资源服务器使用令牌向认证服务器确认令牌的正确性,确认无误后返回资源

Oauth2.0的成员和授权基本流程

  1. Resource Owner(资源拥有者:用户,微信用户)
  2. Client (第三方接入平台:请求者,如掘金)
  3. Resource Server (服务器资源:数据中心,微信用户数据中心)
  4. Authorization Server (认证服务器,微信认证中心)

步骤详解

  1. Authorization Request, 第三方请求用户授权
  2. Authorization Grant,用户同意授权后,会从服务方获取一次性用户授权凭据(如code码)给第三方
  3. Authorization Grant,第三方会把授权凭据(code,授权码)以及服务方给它的的身份凭据(如AppId)一起交给服务方的向认证服务器申请访问令牌
  4. Access Token,认证服务器核对授权凭据等信息,确认无误后,向第三方发送访问令牌Access Token等信息
  5. Access Token,通过这个Access Token向Resource Server索要数据
  6. Protected Resource,资源服务器使用令牌向认证服务器确认令牌的正确性,确认无误后提供资源

授权凭据(code,授权码) 确认了第三方得到了用户的授权 授权凭据(授权码),身份凭据(clientID和clientSecret) 确认了服务方对第三方的信任 token 代表了第三方取得的令牌,在用户允许的范围内,去服务方的资源服务器取得信息

我们可以打个比方,用户张三是一个中国公民,认证中心是国家,国家存有张三的个人资料,第三方机构是银行,资源服务器是国家存储的张三的个人信息

如果说使用BaseAuth,那么我得把身份证(用户名/密码)完全交给银行(第三方客户端),银行(第三方客户端)想干嘛干嘛,不用说你也知道这安不安全.

而到了OAuth2.0,同样还是为了解决信任问题,目的是不交给银行(第三方客户端)身份证的完全使用权,而是用户授权的方式,它是这样解决问题的

张三来到银行,表示张三部分信任这个银行的,愿意把一些身份信息给银行,张三说我是中国公民,我要办卡!这不行吧,张三得刷身份证去国家认证中心认证(类似于微信扫码,github输入用户名密码)

办卡机器上返回了张三的信息,确实是中国公民,张三把身份证装到兜里(这里指OAuth2.0不交给第三方机构,BaseAuth把用户名/密码交给第三方),这时解决了第一个问题,认证中心对用户的信任

用户刷身份证给了银行身份信息的授权之后,返回了各种身份信息(授权码(code)),解决了第二个问题,服务方确认第三方得到了用户对此次服务的授权

办卡是要向国家报备的,银行有国家(认证中心)颁发的营业执照和各种许可,资质(第三方身份凭据,如clientID与clientsecret),这时银行带着资质信息向国家报备,请求许可(token),解决了第三个问题,国家(认证中心)对银行(第三方机构)的信任

最终银行顺利从国家拿到了个人身份信息,完成办卡业务

下一篇详细讲解授权码模式的调用流程