REST - Representational State Transfer - 表述性状态转移 (资源在网络中以某种形式进行状态转移)
REST风格特点:
1.资源
所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。资源总要通过某种载体反应其内容,文本可以用txt格式表现,也可以用HTML格式、XML格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现;JSON是现在最常用的资源表示格式。
结合我的开发实践,我对资源和数据理解如下:
资源是以json(或其他Representation)为载体的、面向用户的一组数据集,资源对信息的表达倾向于概念模型中的数据:
资源总是以某种Representation为载体显示的,即序列化的信息
常用的Representation是json(推荐)或者xml(不推荐)等
Represntation 是REST架构的表现层
2.统一接口
RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和delete,即数据的增删查改)操作,分别对应于HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口,仅通过HTTP方法,就可以完成对数据的所有增删查改工作。
Verd | 描述 |
HEAD(SELECT) | 只获取某个资源的头部信息 |
GET(SELECT) | 获取资源 |
POST(CREATE) | 创建资源 |
PATCH(UPDATE) | 更新资源的部分属性(很少用,一般用POST代替) |
PUT(UPDATE) | 更新资源,客户端需要提供新建资源的所有属性 |
DELETE(DELETE) | 删除资源 |
3.URI
可以用一个URI(统一资源定位符)指向资源,即每个URI都对应一个特定的资源。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或识别符。
一般的,每个资源至少有一个URI与之对应,最典型的URI即URL。
4.无状态
所谓无状态的,即所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。有状态和无状态的区别,举个简单的例子说明一下。如查询员工的工资,如果查询工资是需要登录系统,进入查询工资的页面,执行相关操作后,获取工资的多少,则这种情况是有状态的,因为查询工资的每一步操作都依赖于前一步操作,只要前置操作不成功,后续操作就无法执行;如果输入一个url即可得到指定员工的工资,则这种情况是无状态的,因为获取工资不依赖于其他资源或状态,且这种情况下,员工工资是一个资源,由一个url与之对应,可以通过HTTP中的GET方法得到资源,这是典型的RESTful风格。
5. stateless-auth
由于RESTful风格的服务是无状态的,认证机制尤为重要。例如上文提到的员工工资,这应该是一个隐私资源,只有员工本人或其他少数有权限的人有资格看到,如果不通过权限认证机制对资源做一层限制,那么所有资源都以公开方式暴露出来,这是不合理的,也是很危险的。
认证机制解决的问题是,确定访问资源的用户是谁;权限机制解决的问题是,确定用户是否被许可使用、修改、删除或创建资源。权限机制通常与服务的业务逻辑绑定,因此权限机制需要在每个系统内部定制,而认证机制基本上是通用的,常用的认证机制包括 session auth(即通过用户名密码登录),basic auth,token auth和OAuth,服务开发中常用的认证机制为后三者。
1. Basic Auth是配合RESTful API 使用的最简单的认证方式,只需提供用户名密码即可,但由于有把用户名密码暴露给第三方客户端的风险,在生产环境下被使用的越来越少。因此,在开发对外开放的RESTful API时,尽量避免采用Basic Auth
2. Token Auth并不常用,它与Basic Auth的区别是,不将用户名和密码发送给服务器做用户认证,而是向服务器发送一个事先在服务器端生成的token来做认证。因此Token Auth要求服务器端要具备一套完整的Token创建和管理机制,该机制的实现会增加大量且非必须的服务器端开发工作,也不见得这套机制足够安全和通用,因此Token Auth用的并不多。
3. OAuth(开放授权)是一个开放的授权标准,允许用户让第三方应用访问该用户在某一web服务上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的第三方系统(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。正是由于OAUTH的严谨性和安全性,现在OAUTH已成为RESTful架构风格中最常用的认证机制,和RESTful架构风格一起,成为企业级服务的标配。目前OAuth已经从OAuth1.0发展到OAuth2.0,但这二者并非平滑过渡升级,OAuth2.0在保证安全性的前提下大大减少了客户端开发的复杂性,因此,Gevin建议在实战应用中采用OAuth2.0认证机制。现在网上关于OAuth的资料非常丰富,也有大量开源的第三方库实现了OAuth机制,不熟悉OAuth的同学从OAuth官网入手即可。
6.幂等性
一次请求和多次请求,资源的状态是一样。无论调用多少次都不会产生不同副作用(数据变更)
比如GET和HEAD ,不论你请求多少次,资源还是在那里
DELETE和PUT也是等幂的,因为对同一个资源删除一次或者多次,结果是一样的,就是资源被删除
幂等:
GET: get用于获取资源,不管调用多少次接口,返回结果保持不变,不会改变资源
PUT: put用于更新资源,没有的话则执行创建操作
第一次调用 PUT /tickets/11 , 后台创建 /tickets/11 (帮我看下11号票在不在,在的话更新下状态,不在的话创建下)
第二次调用 PUT /tickets/11 , 后台更新 /tickets/11 (帮我看下11号票在不在,在的话更新下状态,不在的话创建下)
由于两次请求携带的数据是一样的,所以不论请求多少次,最终的结果都是后台存在这么一个资源(创建或更新)
DELETE: delete用于删除资源,会将资源从后台删除。如:
第一次调用 DELETE /tickets/11 , 后台删除 /tickets/11对应的数据信息 (11号票我不要了,帮我删除下吧)
第二次调用 DELETE /tickets/11 , 后台判断 /tickets/11不存在,无操作(11号票我不记得有没有删除,帮我删除下吧)
非幂等:
POST: post用于创建资源,每次调用都会创建一个新的资源
第一次调用 POST /tickets ,后台产生 /tickets/1 这么一个资源(我要新增一张票)
第二次调用 POST /tickets , 后台产生 /tickets/2 这么一个资源(我要再新增一张票)
所以设计Restful API的时候,GET,HEAD, PUT, DELETE一定要设计成幂等。
由于网络是不可靠的,安全性和幂等性就显得特别重要。如果一次请求,服务器收到处理以后,客户端没有收到相应,客户端会再次请求,如果没有等幂性保障,就会发生意想不到的问题