欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Restful规范

程序员文章站 2024-03-22 09:40:40
...

1、关于Restful

随着前后端分离越来越普遍,后端接口规范也就越来越重要了。一套良好的接口规范可以提升工作效率,减少沟通障碍。通常我们都会采用RestfulApi方式来提供接口,使用JSON来传输数据。

Restful是一种软件架构风格,不是标准。既然不是标准,可以遵守,也可以不遵守!!!

2、Api设计6要素

  • 资源路径(URI)

  • HTTP动词(Method)

  • 过滤信息(query-string)

  • 状态码(Status-code)

  • 错误信息(Error)

  • 返回结果(Result)
    Restful规范

3、Restful规范要求

在实际开发中,本着提高工作效率、降低沟通障碍的初衷,使用Restful规范去开发接口时,对于6要素有着以下的要求:

3.1、资源路径(URI)

资源:所有在服务器(电脑)保存的数据(如:音乐/视频/文章/个人信息…)都是服务器端资源.(项目中资源通常都是指的数据表的一条数据)

URI(Uniform Resource Identifier):统一资源标志符,包含URL和URN

URL(Uniform Resource Locator):统一资源定位符

URN(Uniform Resource Name):统一资源名

Restful规范
在HTTP协议中, URI的组成如下:

  • 接口通信协议

    • http
    • https
  • 接口域名

    • 最好是独立解析的域名,如www.xxx.com,域名是需要购买的
  • 端口号

    • http默认为80
    • https默认为443
  • 接口版本

    • 将版本信息放在URI中 http://www.xxx.com/v1
  • 请求路径

    • 网络中的任何东西都为资源,均使用名词表示(一般为复数形式),如针对用户模块请求路径可以为http://www.xxx.com/v1/users/1

3.2、HTTP动词(Method)

对于资源,一般有4个操作:CURD(增/删/改/查)

  • GET: 从服务器获取资源(一项或多项)(查)
  • POST: 在服务器新建一个资源(增)
  • PUT: 在服务器更新资源,服务器返回完整的属性(改)
  • DELETE: 从服务器删除资源(删)【假删,逻辑删除】

以新闻资源为例:URI及HTTP动词设计如下 (资源名称推荐写复数形式)

HTTP动词 URI路径 说明
GET http://域名/news 获取列表数据
GET http://域名/news/:id 根据id获取一条数据
POST http://域名/news 添加一条数据
PUT http://域名/news/:id 根据id修改一条数据
DELETE http://域名/news/:id 根据id“删除“一条数据

上述形式的URI路径(路由)称之为资源路由

3.3、过滤信息(query-string)

通常也叫做请求参数或查询字符串(“?id=1&age=213”)。

3.4、状态码(Status-code)

成功发送的请求必有响应(响应可能没有响应体,但是状态码肯定有),每个响应都会有一个状态码。在Restful风格编写接口时常见的HTTP请求状态码有:

状态码 含义 说明
200 OK 操作成功, 并返回数据
400 Bad Request 请求语法错误
403 Forbidden 请求没有权限的资源
404 Not Found 没有找到请求的资源
405 Method Not Allowed 请求动词使用错误
500 Internal Server Error 服务器(配置)内部错误

更为详尽的状态码参考:

**GET **

200(OK) - 表示已在响应中发出

204(No Content) - 资源有空表示

301(Moved Permanently) - 资源的URI已被更新

303(See Other) - 其他(如,负载均衡)

304(not modified)- 资源未更改(缓存)

400 (bad request)- 指代坏请求(如,参数错误)

404 (not found)- 资源不存在

406 (not acceptable)- 服务端不支持所需表示

500 (internal server error)- 通用错误响应

503 (Service Unavailable)- 服务端当前无法处理请求

**POST **

200(OK)- 如果现有资源已被更改

201(created)- 如果新资源被创建

202(accepted)- 已接受处理请求但尚未完成(异步处理)

301(Moved Permanently)- 资源的URI被更新

303(See Other)- 其他(如,负载均衡)

400(bad request)- 指代坏请求

404 (not found)- 资源不存在

406 (not acceptable)- 服务端不支持所需表示

409 (conflict)- 通用冲突

412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)

415 (unsupported media type)- 接受到的表示不受支持

500 (internal server error)- 通用错误响应

503 (Service Unavailable)- 服务当前无法处理请求

**PUT **

200 (OK)- 如果已存在资源被更改

201 (created)- 如果新资源被创建

301(Moved Permanently)- 资源的URI已更改

303 (See Other)- 其他(如,负载均衡)

400 (bad request)- 指代坏请求

404 (not found)- 资源不存在

406 (not acceptable)- 服务端不支持所需表示

409 (conflict)- 通用冲突

412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)

415 (unsupported media type)- 接受到的表示不受支持

500 (internal server error)- 通用错误响应

503 (Service Unavailable)- 服务当前无法处理请求

**DELETE **

200 (OK)- 资源已被删除

301 (Moved Permanently)- 资源的URI已更改

303 (See Other)- 其他,如负载均衡

400 (bad request)- 指代坏请求

404 (not found)- 资源不存在

409 (conflict)- 通用冲突

500 (internal server error)- 通用错误响应

503 (Service Unavailable)- 服务端当前无法处理请求

3.5、错误信息(Error)

如果状态码是4xx或者5xx, 需要告诉客户端对应的错误信息。通常以Json格式返回,形式如下:

{
	'error': '错误信息',
    'code': '错误编号',
    'msg': '资源没找到',
    'message': 'xxxx',
    'text': 'xxxx',
    'reason': 'xxxxxx'
}

3.6、返回结果(Result)

针对不同的操作,服务需要返回的结果应该符合这样的规范:

  • GET /collections – 返回资源列表(数组对应的json格式)

  • GET /collections/:id – 返回单个资源 eg. /collections/1

  • POST /collections – 返回新生成的资源

  • PUT /collections/:id – 返回资源的完整属性

  • DELETE /collections/:id – 返回204状态码+空文档

实际开发中,通常会将状态码、错误信息、返回数据,都放到返回结果中(一般以json格式返回)。例如:

{
    "code":200, 
    "msg":"success", 
    "goods":{
        "id":1,
        "goods_name":"华为P100 pro plus",
        "goods_price": 9999.99,
        "currency": "CNY",
        "stock": 1288,
        .......
    }
}

返回的数据中,节点的key名字要遵循见名知义

4、接口安全

前后端分离式开发需要进行数据交互,传输的数据被偷窥、被抓包、被伪造时有发生,那么如何设计一套比较安全的API接口方案呢?

并不是所有的接口都需要考虑安全的,有些接口是公开的,任何人只要知道地址都可以调用,对于一些项目中需要用户登录才能访问的接口才需要考虑安全问题。

一般解决的方案有以下几类:

  • token令牌认证(jwt)
  • AK(app key)&SK(secret key)【用户名&密码】
  • 时间戳超时验证+签名算法字符串
  • URL签名(算法,非对称算法)
  • 数据脱敏(防范数据库数据泄露)
  • HTTPS
    • 数字证书(防运营商)
  • IP黑/白名单(服务器层面的限制,apache、nginx)
  • oAuth2.0

关于JWT

Json web token(JWT),是基于token的鉴权机制,类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息,为应用的扩展提供了便利。JWT具备以下几个优点:

  • 因json的通用性,所以JWT是可以进行跨语言

  • JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息

  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的

  • 它不需要在服务端保存会话信息,所以它非常适合应用在前后端分离的项目上

使用JWT进行鉴权的工作流程如下(重点):

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息(查数据库)
  • 服务器通过验证发送给用户一个token(令牌)
  • 客户端存储token(Vuex+localStorage),并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

Restful规范
JWT是由三段信息构成的(头部、载荷、签名),将这三部分使用.连接在一起就组成了JWT字符串,形如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjNmMmc1N2E5MmFhIn0.eyJpYXQiOjE1NTk1Mjk1MjksImlzcyI6Imh0dHA6XC9cL3d3dy5weWcuY29tIiwiYXVkIjoiaHR0cDpcL1wvd3d3LnB5Zy5jb20iLCJuYmYiOjE1NTk1Mjk1MjgsImV4cCI6MTU1OTUzMzEyOSwianRpIjoiM2YyZzU3YTkyYWEiLCJ1c2VyX2lkIjoxfQ.4BaThL6_TbIMBGLIWZgpnoDQ-JlAjzbiK3y3BcvNiGI

其中:

  • 头部(header),包含了两(可以更多)部分信息,分别是类型的声明和所使用的加密算法。

一个完整的头部就像下面的JSON:

{
  'typ': 'JWT',
  'alg': 'HS256'
}

然后将头部进行base64加密/编码(该加密是可以对称解密的),这就得到了jwt的第一部分。

  • 载荷(payload),载荷就是存放有效信息的地方。这些有效信息包含三个部分
    • 标准中约定声明(建议但不强制)
    • 公共的声明
    • 私有的声明

定义一个payload:

{
  "sub": "1234567890",
  "name": "John",
  "admin": true
}

依旧进行base64加密,这就得到了jwt的第二部分。

  • 签名(signature),这个签证信息由三部分组成:
    • 经过base64编码后的
      • header
      • payload
    • secret(就是一个字符串,自己定义,值是什么无所谓)

例如:

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');

这样就得到了jwt的第三部分。

最终将三部分信息通过.进行连接就得到了最终的jwt字符串。

需要注意的是

  • secret是保存在服务器端的
  • jwt的签发生成也是在服务器端的
  • secret是用来进行jwt的签发和jwt的验证

所以,secret它就是服务端的私钥,在任何场景都不应该泄露出去。一旦其他人(包括客户端的用户)得知这个secret,那就意味着他们可以自我签发jwt,接口就没有安全性可言了。