密码学基础
在正式讲解HTTPS协议之前,我们首先要知道一些密码学的知识。
明文: 明文指的是未被加密过的原始数据。
密文:明文被某种加密算法加密之后,会变成密文,从而确保原始数据的安全。密文也可以被解密,得到原始的明文。
密钥:密钥是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的参数。密钥分为对称密钥与非对称密钥,分别应用在对称加密和非对称加密上。
对称加密:对称加密又叫做私钥加密,即信息的发送方和接收方使用同一个密钥去加密和解密数据。对称加密的特点是算法公开、加密和解密速度快,适合于对大数据量进行加密,常见的对称加密算法有DES、3DES、TDEA、Blowfish、RC5和IDEA。
加密过程如下:明文 + 加密算法 + 私钥 => 密文
解密过程如下:密文 + 解密算法 + 私钥 => 明文
对称加密中用到的密钥叫做私钥,私钥表示个人私有的密钥,即该密钥不能被泄露。 其加密过程中的私钥与解密过程中用到的私钥是同一个密钥,这也是称加密之所以称之为“对称”的原因。由于对称加密的算法是公开的,所以一旦私钥被泄露,那么密文就很容易被破解,所以对称加密的缺点是密钥安全管理困难。
非对称加密:非对称加密也叫做公钥加密。非对称加密与对称加密相比,其安全性更好。对称加密的通信双方使用相同的密钥,如果一方的密钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对密钥,即公钥和私钥,且二者成对出现。私钥被自己保存,不能对外泄露。公钥指的是公共的密钥,任何人都可以获得该密钥。用公钥或私钥中的任何一个进行加密,用另一个进行解密。 被公钥加密过的密文只能被私钥解密
加密过程如下:明文 + 加密算法 + 公钥 => 密文
解密过程如下:密文 + 解密算法 + 私钥 => 明文
由于加密和解密使用了两个不同的密钥,这就是非对称加密“非对称”的原因。 非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。 在非对称加密中使用的主要算法有:RSA、Elgamal、Rabin、D-H、ECC(椭圆曲线加密算法)等。
Hash算法:是把任意长度的输入信息通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。常见算法有MD5、SHA-1、SHA-2、SHA-256等
简介
HTTP 协议(HyperText Transfer Protocol,超文本传输协议):是客户端浏览器或其他程序与Web服务器之间的应用层通信协议 。HTTPS(全称:HyperText Transfer Protocol over Secure Socket Layer),相比HTTP多了一层“SSL/TLS”,SSL/TLS层负责客户端和服务器之间的加解密算法协商、密钥交换、通信连接的建立,使用了以下三种算法:
- 非对称加密,用于HTTPS握手阶段的身份认证和密钥协商
- 对称加密,双方使用协商的密钥加解密传输数据
- Hash算法,用于确保通信过程的信息完整
SSL的全称是Secure Sockets Layer,即安全套接层协议,是为网络通信提供安全及数据完整性的一种安全协议。SSL协议在1994年被Netscape发明,后来各个浏览器均支持SSL,其最新的版本是3.0
TLS的全称是Transport Layer Security,即安全传输层协议,是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。在TLS与SSL3.0之间存在着显著的差别,主要是它们所支持的加密算法不同,所以TLS与SSL3.0不能互操作。虽然TLS与SSL3.0在加密算法上不同,但是在我们理解HTTPS的过程中,我们可以把SSL和TLS看做是同一个协议。
SSL/TLS安全套接层的发展历程:
其中SSL1.0未发布,SSL2.0存在严重漏洞,现在主流HTTPS使用TLSv1.2,基本不再使用低于 TLSv1 的版本
不使用SSL/TLS的HTTP通信,所有信息明文传播,会带来三大风险:
- 窃听风险:第三方可以获取通信内容;
- 篡改风险:第三方可以修改通信内容;
- 冒充风险:第三方可以冒充他人进行通信。
SSL/TLS协议是为了解决这三大风险而设计的,以期达到:
- 信息加密传输:第三方无法窃听;
- 校验机制:一旦被篡改,通信双方会立刻发现;
- 身份证书:防止身份被冒充。
虽然HTTPS显著提高了数据传输的安全性,但其通信效率是一个不可忽视的问题,HTTP通信时只需要经理TCP的三次握手即可建立连接,HTTPS除了TCP的三次握手外,还需要SSL的握手,而SSL握手耗时大约是TCP握手的三倍左右
HTTPS在传输数据之前需要客户端与服务端之间进行一次握手(两次完整的HTTP请求,非TCP握手),在握手过程中通过非对称加密确立双方加密传输数据的密码信息,握手完成后双方使用协商好的会话密钥通过对称加密进行数据传输
发展历程
- HTTP/0.9:1991年发布,极其简单,只有一个get命令
- HTTP/1.0:1996年5月发布,增加了大量内容
- HTTP/1.1:1997年1月发布,进一步完善HTTP协议,是目前最流行的版本
- SPDY:2009年谷歌发布SPDY协议,主要解决HTTP/1.1效率不高的问题
- HTTP/2:2015年借鉴SPDY的HTTP/2发布
- HTTP/3:2022年6月正式发布,标准文档为RFC 9114
HTTP/0.9
HTTP 0.9的核心作用是传输超文本内容 HTML。
只定义了一种方法:GET + 请求的文件路径,服务端收到请求后返回一个以 ASCII 字符流编码的 HTML 文档。
HTTP/1.0
HTTP 1.0的核心改变是引入头部字段,不仅用于解决不同类型文件传输的问题,也可以实现其他很多功能如缓存、认证信息等。
HTTP 1.0 相对于 HTTP 0.9 的改进如下:
- 每个请求都附加了 HTTP 版本。
- 在响应开始时发送状态代码。
- 请求和响应都包含 HTTP 报文头。
- 报文头中的元数据使协议具有灵活性和可扩展性。
- 内容类型能够传输 HTML 文件以外的文档。
但是,HTTP 1.0 不是官方标准。
HTTP/1.1
HTTP 1.1作为HTTP 的第一个标准化版本,核心改变是解决HTTP1.0的短连接问题,建立了长连接进行复用。
- 缓存处理:HTTP/1.0 使用 Pragma:no-cache + Last-Modified/If-Modified-Since来作为缓存判断的标准;HTTP/1.1 引入了更多的缓存控制策略:Cache-Control、Etag/If-None-Match等
- 错误状态管理:HTTP/1.1新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
- 范围请求:HTTP/1.1在请求头引入了range头域,它允许只请求资源的某个部分,也就是断点续传,如碰到网络故障,可以从已经上传/下载的部分开始继续上传/下载未完成的部分,返回码是206(Partial Content),这样就方便了开发者*的选择以便于充分利用带宽和连接
- Host头:HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础,比如一台IP为10.8.56.13的服务器上部署这很多个服务或网站。Host 请求头能够决定访问哪个网站或者服务。
- 持久连接:HTTP/1.1 最大的变化就是引入了持久连接(persistent connection),在HTTP/1.1中默认开启 Connection: keep-alive,即TCP连接默认不关闭,可以被多个请求复用
- 客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
- 管道机制:HTTP/1.1中引入了管道机制(pipelining),即在同一个TCP连接中,客户端可以同时发送多个请求
HTTP/1.1对头阻塞
HTTP/1.1 的持久连接和管道机制允许复用TCP连接,在一个TCP连接中,也可以同时发送多个请求,但是所有的数据通信都是按次序完成的,服务器只有处理完一个回应,才会处理下一个回应。比如客户端需要A、B两个资源,管道机制允许浏览器同时发出A请求和B请求,但服务器还是按照顺序,先回应A请求,完成后再回应B请求,这样如果前面的回应特别慢,后面就会有很多请求排队等着,这称为"队头阻塞(Head-of-line blocking)"
HTTP/2
HTTP/2以Google发布的SPDY协议为基础,于2015年发布。它不叫HTTP/2.0,因为标准委员会不打算再发布子版本了,下一个新版本将是HTTP/3。HTTP/2协议只在HTTPS环境下才有效,升级到HTTP/2,必须先启用HTTPS。HTTP 2.0的核心改变是默认不再使用 ASCII 编码传输,而是改为二进制数据,来提升传输效率。有了二进制分帧后,对于同一个域,客户端只需要与服务端建立一个连接即可完成通信需求,这种利用一个连接来发送多个请求的方式称为「多路复用」。实现多路复用技术解决对头阻塞问题。主要特点如下:
- 二进制分帧:HTTP/1.1的头信息是文本(ASCII编码),数据体可以是文本,也可以是二进制;HTTP/2 头信息和数据体都是二进制,统称为“帧”:头信息帧和数据帧;
- 多路复用(双工通信):通过单一的 HTTP/2 连接发起多重的请求-响应消息,即在一个连接里,客户端和浏览器都可以同时发送多个请求和响应,而不用按照顺序一一对应,这样避免了“队头堵塞”。HTTP/2 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上双向交换消息。
- 数据流:因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。HTTP/1.1取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
- 首部压缩:HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息压缩后再发送(SPDY 使用的是通用的DEFLATE 算法,而 HTTP/2 则使用了专门为首部压缩而设计的 HPACK 算法)。;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
- 服务端推送:HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。
HTTP/3
QUIC(Quick UDP Internet Connection)是谷歌制定的一种基于UDP的低时延的互联网传输层协议,在新正在制定的HTTP/3协议标准中,传输层协议由TCP替换为基于UDP的QUIC协议,解决TCP连接慢、对头拥塞等问题。与TCP协议相比,UDP更为轻量,错误校验也要少得多,因此UDP往往效率更高,但可靠性较差。
QUIC很好的解决了当今传输层和应用层面临的各种需求,包括处理更多的连接、安全性和低延迟。QUIC融合了包括TCP,TLS、HTTP/2等协议的特性,但基于UDP传输。
HTTP3是在保持QUIC稳定性的同时使用UDP来实现高速度(选择QUIC就是选择UDP), 同时又不会牺牲TLS的安全性.
HTTP2协议虽然大幅提升了HTTP/1.1的性能,然而,基于TCP实现的HTTP2遗留下3个问题:
- 有序字节流引出的队头阻塞(Head-of-line blocking),使得HTTP2的多路复用能力大打折扣;
- TCP与TLS叠加了握手时延,建链时长还有1倍的下降空间;
- 基于TCP四元组确定一个连接,这种诞生于有线网络的设计,并不适合移动状态下的无线网络,这意味着IP地址的频繁变动会导致TCP连接、TLS会话反复握手,成本高昂。
HTTP3协议解决了这些问题:
- HTTP3基于UDP协议重新定义了连接,在QUIC层实现了无序、并发字节流的传输,解决了队头阻塞问题(包括基于QPACK解决了动态表的队头阻塞);
- HTTP3重新定义了TLS协议加密QUIC头部的方式,既提高了网络攻击成本,又降低了建立连接的速度(仅需1个RTT就可以同时完成建链与密钥协商);
- HTTP3 将Packet、QUIC Frame、HTTP3 Frame分离,实现了连接迁移功能,降低了5G环境下高速移动设备的连接维护成本。
总结
协议版本 |
解决的核心问题 |
解决方式 |
0.9 |
HTML 文件传输 |
确立了客户端请求、服务端响应的通信流程 |
1 |
不同类型文件传输 |
设立头部字段 |
1.1 |
创建/断开 TCP 连接开销大 |
建立长连接进行复用 |
2 |
并发数有限 |
二进制分帧、多路复用 |
3 |
TCP对头阻塞、网络延时 |
基于UDP的QUIC协议代替TCP协议 |
数字证书
证书 = 公钥(服务方生成密码对中的公钥)+ 申请者与颁发者信息 + 签名(用CA机构生成的密码对的私钥进行签名)
CA证书
CA是Certificate Authority的缩写,也叫证书颁发机构,即颁发数字证书的机构,是公钥基础设施(Public Key Infrastructure,PKI)的核心,也是受信任的第三方机构,是负责签发证书、认证证书、管理已颁发证书的机关,目的就是为了让企业组织和用户的信息数据等能够在互联网环境下更加安全。
- 第三方认证机构完整的签发管理流程及行业认可度,包括签发,递送等过程加密且可追溯,泄露事故保障等等;
- 一种除己以外的第三方信任原则,即在认证方与被认证方中间加入一个公正可信任的独立第三方的签发中心,把认证方与被认证方隔离开来,可以将安全风险降到最低
证书颁发机构(也称为CA机构)是受信任的组织,要成为CA机构,需要得到行业认可,同时更需要具备相关的技术服务标准,才能保证签发的SSL证书真实可信,如果一旦发生SSL证书安全问题,还需要具备高额的赔付保障。这些条件使得成为CA机构门槛较高,所以也具备了权威性。
CA机构与浏览器厂家都会接受 CA/浏览器论坛
来确定CA机构与浏览器信任体,CA机构用于验证网站(实名及实体认证),这样才可以知道您在和谁进行互联网通信。他们的目标是使互联网成为组织和用户都更安全的场所。
受信任的CA也称商业CA,据统计,全球有数百个公共CA,通常它们是按国家地区进行划分的。但是,实际上排名靠前的也有大约数十个,比如 Digicert,Sectigo,GlobalSign,Entrust 等等。
CA 拥有一个证书(内含公钥和私钥)。网上的公众用户通过验证 CA 的签字从而信任 CA ,任何人都可以得到 CA 的证书(含公钥),用以验证它所签发的证书。如果用户想得到一份属于自己的证书,他应先向 CA 提出申请。在 CA 判明申请者的身份后,便为他分配一个公钥,并且 CA 将该公钥与申请者的身份信息绑在一起,并为之签字后,便形成证书发给申请者。
CA证书的功能:
- 颁发证书,颁发证书其实就是使用CA的私钥对证书请求签名文件CSR进行签名;
- 颁发的证书浏览器要信任,浏览器只需要用CA的公钥进行验签成功就表示这个证书是合法可信的,这就需要浏览器内置CA的公钥,也就是内置CA的证书。一般来说,操作系统都会内置权威CA的证书,有的浏览器会使用操作系统内置的CA证书列表,有的浏览器则自己维护的CA证书列表,比如Firefox。
内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名,即自签名证书
SSL证书
SSL证书和CA证书是从属关系,因为SSL是众多CA证书中的一种。CA是数字证书管理机构,SSL证书一种数字证书,SSL证书由CA机构签发的。
实际上,我们使用的证书分很多种类型,SSL证书只是其中的一种。证书的格式是由X.509标准定义。SSL证书负责传输公钥,是一种PKI(Public Key Infrastructure,公钥基础结构)证书。
我们常见的证书根据用途不同大致有以下几种:
- SSL证书,用于加密HTTP协议,也就是HTTPS。
- 代码签名证书,用于签名二进制文件,比如Windows内核驱动,Firefox插件,Java代码签名等等。
- 客户端证书,用于加密邮件。
- 双因素证书,网银专业版使用的USB Key里面用的就是这种类型的证书。
这些证书都是由受认证的证书颁发机构——我们称之为CA(Certificate Authority)机构来颁发,针对企业与个人的不同,可申请的证书的类型也不同,价格也不同。CA机构颁发的证书都是受信任的证书,对于SSL证书来说,如果访问的网站与证书绑定的网站一致就可以通过浏览器的验证而不会提示错误。
一般的数字证书包含的内容:
- 申请者公钥
- 申请者的组织信息和个人信息
- 签发机构 CA的信息
- 有效时间
- 证书序列号等信息的明文
- 域名CN
- 签名
- 使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA的私钥对信息摘要进行加密,加密后形成的密文即签名。
验证证书时,客户端读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应CA的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;
客户端验证证书的合法性,如果验证通过才会进行后续通信,否则根据错误情况不同做出提示和操作,合法性验证包括如下:
- 证书链的可信性Trusted Certificate Path;
- 证书是否吊销 Revocation,有两类方式离线 CRL 与在线 OCSP,不同的客户端行为会不同;
- 有效期Expiry Date,证书是否在有效时间范围;
- 域名Domain,核查证书域名是否与当前的访问域名匹配,匹配规则后续分析;
SSL证书验证失败有以下三点原因:
- SSL证书不是由受信任的CA机构颁发的
- 证书过期
- 访问的网站域名与证书绑定的域名不一致
证书申请验证流程
- 服务方S向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;(不交私钥)
- CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
- 如信息审核通过,CA会向申请者签发认证文件-证书。
HTTPS通信过程
一个HTTPS请求实际上包含了两次HTTP传输,可以细分为8步。
- 客户端向服务器发起HTTPS请求,连接到服务器的HTTPS端口
- 以明文传输请求信息,包含版本信息,加密套件候选列表,压缩算法候选列表,随机数,扩展字段等信息:
- 支持的最高 TLS 协议版本 version;
- 客户端支持的加密套件 cipher suites 列表, 每个加密套件对应前面TLS原理中的四个功能的组合:认证算法 Au (身份验证)、密钥交换算法 KeyExchange(密钥协商)、对称加密算法 Enc (信息加密)和信息摘要 Mac(完整性校验);
- 支持的压缩算法 compression methods 列表,用于后续的信息压缩传输;
- 随机数 random_C,用于后续的密钥的生成;
- 扩展字段 extensions,支持协议与算法的相关参数以及其它辅助信息等,常见的 SNI 就属于扩展字段,后续单独讨论该字段作用
- 服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人。
- 服务器返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 等,其中随机数用于后续的密钥协商,并将自己的公钥发送给客户端。
- 客户端收到服务器端的证书(公钥)之后,会验证其合法性,如果发现发现证书有问题,会中断HTTPS连接或者提示https warning。如果公钥合格,客户端会生成一个随机数字 Pre-master,计算得到会话密钥:enc_key=Fuc(random_C, random_S, Pre-Master),至此,HTTPS中的第一次HTTP请求结束。
- 客户端会发起HTTPS中的第二个HTTP请求,将使用服务端公钥加密之后的Pre-master和一段用enc_key加密过后的encrypted_handshake_message发送给服务器。
- 服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密出Pre-Master,通过Fuc(random_C, random_S, Pre-Master)计算出会话密钥enc_key,并用enc_key对发送过来的encrypted_handshake_message数据进行解密,验证数据和密钥的正确性。
- 服务端同样使用enc_key加密encrypted_handshake_message发送给客户端
- 客户端收到服务器发送来的密文,用enc_key对其进行对称解密,验证通过后标识HTTPS中的第二个HTTP请求结束,整个HTTPS握手阶段完成。之后客户端和服务端可以使用enc_key进行数据加密传输
部分情况下客户端也会要求服务端进行客户端证书认证,如下图所示,双向认证时在原有流程上增加服务端对客户端证书的验证以及使用公钥和私钥对服务端选择的加密方案的加解密过程,验证通过后再进行密钥协商等流程:
单向认证所需证书的标准要求:server.crt、server.key、ca.crt、ca.key
不标准要求:server.crt、server.key
curl提供了-k/--insecure选项,该选项可以忽略根证书验证;另外,浏览器访问HTTPS网址时一般都支持跳过根证书的验证,因此HTTPS单向认证使用的证书只适用于数据传输加密,没有认证鉴权功能,Kubernetes通过验证证书的CN和O参数来验证证书的用户名和组并不是通用的做法。
双向认证所需的证书要求:client.crt client.key ca.crt ca.key server.crt、server.key 共六个
REST与HTTP
REST
REST(Resource Representational State Transfer),翻译是”表现层状态转化”,是Roy Thomas Fielding在他2000年的博士论文中提出的,是所有Web应用都应该遵守的架构设计指导原则,用于描述API接口,本质是一种软件架构风格。HTTP接口按照REST风格设计就是Restful HTTP,WebService接口按照REST风格设计 就是Restful WebSerivce。
面向资源是REST最明显的特征,对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST要求,必须通过统一的接口来对资源执行各种操作(GET/PUT/PATCH等)。
Restful主要解决的问题:
- 降低开发的复杂性
- 提高系统的可伸缩性
Restful资源层Resource:文本、图片、服务、音频等等。
Restful表现层Representational:
- 文本:txt、html、xml、json、二进制
- 图片:jpg、png
- Case:book是一个资源,获取不同的格式
- http协议的content-type和accept
Restful状态转化State Transfer:
- 幂等性:每次HTTP请求相同的参数,相同的URI,产生的结果是相同的
- GET
- POST
- PUT
- DELETE
对于Restful风格的API,需要遵循以下原则:
- C/S模型,通过统一接口通讯
- 层次化,可与多个服务器通讯
- 无状态,服务器不保存客户状态,发送请求时需包含足够信息
- Cache,C/S之间可使用缓存
- 唯一资源标识来标识资源,对资源操作不会改变这些标识
- 传递消息的自身描述
- 返回资源的自身描述
- 可选的超媒体即应用状态引擎(HATEOAS)
示例:
使用传统方法进行请求等操作:
http://127.0.0.1/item/queryItem?id=1 查询,GET
http://127.0.0.1/item/saveItem 新增,POST
http://127.0.0.1/item/updateItem 更新,POST
http://127.0.0.1/item/deleteItem?id=1 删除,GET或POST
改用RESTful风格后:
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
可以对item一个接口进行增、删、改、查四种操作。请求地址一样,但是功能可以不同。是通过用HTTP协议里的动词来实现资源的添加,修改,删除等操作,即通过HTTP动词来实现资源的状态扭转。
URI
网络上的所有事物都可以被抽象为资源,REST资源代表网络上的一个实体,或者说是网络上的一个具体信息:
schema://host[:port]/path [?query-string][#anchor]
- schema:指定底层使用的协议(例如:http,https,ftp)
- host:服务器的IP地址或者域名
- port:服务器端口,默认为80
- path:访问资源的路径
- query-string:发送给http服务器的数据
- anchor:锚
URL(Uniform Resource Locator): 统一资源定位符,偏重定位,说明了通过哪种协议来访问一个资源。
URN(Uniform Resource Name): 统一资源名称
URI:统一资源标识符,偏重标识,一个字符串格式规范,URL和。
URL和URN是URI的子集,因为URI是资源标识,URL是指定用哪种协议访问该资源
Web上地址的基本形式是URI,它有两种形式:
- 一种是URL,这是目前URI的最普遍形式。
- 另一种就是URN,这是URL的一种更新形式,URN不依赖于位置,并且有可能减少失效连接的个数。但是其流行还需假以时日,因为它需要更精密软件的支持。
URL |
URI |
|
具体名称 |
Uniform Resource Lacator, 统一资源定位符 |
Uniform Resource Identifier, 统一资源标识符 |
含义 |
在WWW上,每一信息资源都有统一的且唯一的地址, 该地址就是URL |
广义上的资源标识,既包括网络也可涵盖本地等 凡是标识资源的均可称为URI |
组成 |
三部分: 【协议/服务方式】 【该资源的主机IP地址(时含端口号)】 【主机资源的具体地址】 e.g. [协议]://[主机地址]:(端口)/[路径] |
两段: 【特定协议】 及【协议内容的语法和语义】 e.g. [协议名]://[用户名]:[密码]@[服务器地址]:[服务器端口号]/[路径]?[查询字符串]#[片段ID] |
设计Restful API应该考虑以下信息:
- 资源路径(URI)
- HTTP动词
- GET:请求获取Request-URI所标识的资源
- POST:新创建资源,在Request-URI所标识的资源后附加新的数据
- PUT:请求服务器存储一个资源,并用Request-URI作为其标识。向指定资源位置上传最新的完整资源
- DELETE:请求服务器删除Request-URI所标识的资源
- HEAD:请求获取由Request-URI所表示的资源的响应消息报头,可以不用传入全部内容
- PATCH:在服务器更新资源(客户端提供改变的属性)
- OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求
- 过滤信息
- 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。例如:
- ?offset=10:指定返回记录的开始位置
- ?page=2&per_page=100:指定第几页,以及每页的记录数
- ?sortby=name&order=asc:指定返回结果排序,以及排序顺序
- ?animal_type_id=1:指定筛选条件
- 状态码
- 其所有操作可能返回的状态码信息如下:
- 1xx:信息响应类,表示接收到请求并且继续处理
- 2xx:处理成功响应类,表示动作被成功接收、理解和接受
- 3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
- 4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
- 5xx:服务器端错误,服务器不能正确执行一个正确的请求
- 其常见返回状态码如下所示:
- 200 OK 客户端请求成功
- 400 Bad Request 客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized 服务器收到请求,但是拒绝提供服务
- 404 Not Found 请求资源不存在
- 500 Internal Server Error 服务器发生不可预期的错误
- 503 Server Unavailable 服务器当前不能处理客户端的请求
HTTP协议
- 工作流程
HTTP是以TCP作为底层协议,默认端口号为80.通信过程:
- 客户机与服务器建立连接。
- 服务端在80端口等待客户的请求。
- 客户端发送一个请求到服务器。
请求报文中会包含以下几个东西:请求行、请求头、请求空行、请求体
POST /user HTTP/1.1 # 请求行,用来说明请求类型,要访问的资源以及所使用的 HTTP 版本
Host: www.user.com
Content-Type: application/x-www-form-urlencoded
accept: application/json
User-agent: Mozilla/5.0. # 以上是首部
#(此处必须有一空行) # 空行分割header和请求内容
name=world # 请求体
常见的请求头:
Host:主机名,一般是域名 Connection:连接类型,如Keep-Alive,http1.1默认长连接 Origin:用来说明请求从哪里发起的 USer-Agent(用户代理):浏览器类型,操作系统信息 Accept:能接收的数据类型:如:text/html、image/jpeg Accept-Encoding:接受的压缩格式,如gzip Accept-Language:接收的语言,如zh-CN,zh表示中文,CN表示中国 Cookie:表示服务器端为本次访问分配了一个Session ID,每次发送请求时都会主动将该Session ID通过Cookie字段又发送回服务器,用于验证身份和保持状态。
- 服务器接收来自客户端的请求并给出响应
服务端进行对应的处理会给我们返回一个响应,每一个响应都会有一个响应报文,在响应报文中会包含我们所有的响应信息(也就是服务端在接受到客户端请求以后,给我们的回信) 响应报文中会包含几个信息:
- 状态行
HTTP/1.1 200 OK
HTTP/1.1 服务器使用的 HTTP 协议版本
# 200 响应状态码
# OK 对响应状态码的简单解释
- 响应头(常见)
Date: Jan, 14 Aug 2019 12:42:30 GMT # 服务器时间
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45 # 服务器类型
Content-Type: text/html # 服务端给客户端的数据类型
Content-Length: 11 # 服务端给客户端的数据长度
- 响应体
hello world
服务端给客户端的响应数据
- 关闭TCP连接
- HTTP请求方法
HTTP1.0 定义了三种请求方法: GET、POST 和 HEAD 方法。
HTTP1.1 新增了六种请求方法: OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
序号 |
方法 |
描述 |
1 |
GET |
请求指定的页面信息,并返回实体主体 |
2 |
HEAD |
类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 |
POST |
向指定资源提交数据进行处理请求,数据被包含在请求体中。POST 请求可能会导致新的资源的建立/或已有资源的修改 |
4 |
PUT |
从客户端向服务器传送的数据取代指定的文档的内容 |
5 |
DELETE |
请求服务器删除指定的资源 |
6 |
PATCH |
是对 PUT 方法的补充,用来对已知资源进行局部更新 |
7 |
TRACE |
回显服务器收到的请求,主要用于测试或诊断 |
8 |
OPTIONS |
允许客户端查看服务器的性能 |
9 |
CONNECT |
HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器 |
- URL
URL,全称:Uniform Resource Locator 译名:统一资源定位符,用于准确描述Internet上某一资源的地址;
通常我们访问的网页都是有一个URL地址,或称Web地址,俗称:网址。
URL格式:以http://test.com:8080/example/index.html
为例进行说明。
URL的格式由下列三部分组成:
- 第一部分是协议(或称为服务方式),本例中为
HTTP 协议
。 - 第二部分是存有该资源的主机IP地址或域名(有时也包括端口号),本例中为
test.com:8080
。平时看到的都是域名,之后客户端会通过DNS(域名系统) 查询域名对应的 IP,然后根据IP和端口号进行服务器的连接。稍后会对此进行详细说明。 - 第三部分是主机资源的具体地址,如目录和文件名等,本例中为
/example/index.html
。
URL通用语法
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
- scheme: 协议,常见的有 http(80),https(443),ftp(21),file。
- user:用户名。
- password: 密码。
如使用ftp协议传输时需要输入用户名和密码,但是我们的http协议中,如果把用户名和密码就放在url里,那很不安全,所以一般不这样用
- host:主机。
- port: 端口。
- path:路径。
- params: 参数。通常为
key=value
。
参数一般使用“;”与路径分开,如果有多个参数也使用“;”分隔开,我们访问一些资源,只有路径端口是不够的,有时候需要向解析url的应用程序提供参数才能去访问资源,如参数可能会定义传输格式等等
- query:查询参数或查询字符串。
查询参数使用“?”与前边的东西分开,如果有多个查询的问题,需要使用“&”连接。访问一些资源时,有些需要查询数据库进行搜索来缩小请求资源范围,就像我们查东西时指定关键字一样,如?name=bob&id=123,意思是,在该路径下,查询name=bob,id=123的资源
- frag: 片段。
我们访问资源时,可以不直接访问该资源,而是访问资源的一部分。片段用“#”与其它东西分开,后边写指定部分的名字。如#main,表示访问资源/index.html 中的名字叫做main的部分。其实http服务器仍然是把整个对象资源发给你的浏览器,浏览器获得整个资源后,根据片段显示你要的资源。
这只是通用语法,并不是每种URL都会有上面的所有信息,其中最重要的 3 个部分是:协议(scheme)、主机(host)和路径(path)。
示例:
基于对HTTP协议的学习,在url中?之后以key1=value1&key2=value2格式编辑的内容是url上的参数,这里以一个简单的api中的获取图片接口进行请求:
接口说明文档:https://api.apiopen.top/swagger/index.html#
获取图片的接口url地址:https://api.apiopen.top/api/getImages?page=15&size=2
在url中可以修改page和size的值,所代表含义分别是页码和查询数量,比如将size值改为1,就会看到返回体中只有一条查询结果记录。
总结
一般的HTTP接口只有POST和GET方法,其所有请求参数都填在Body中,参数类型是由服务端固定的,但Restful API让我们设计接口时一定要适当使用PUT和DELETE方法,其参数可以填在URL中,每个URL都对应服务端的一个资源,URL中的命名都是名词,通过不同的操作(GET、POST等)实现不同的动作,另外请求中传输的参数类型是可变的,通过HTTP Header中的Accept和Content-Type参数指定传输内容的数据格式。
虽然Restful风格的API能帮助我们设计出更规范的API接口,降低开发的复杂性和提高系统的可伸缩性,但如果我们仅仅只是为了实现某个功能,而不用考虑对外暴露自己的API,完全可以忽略Restful风格的设计
常用开源项目与HTTP关系
HTTP1.0 |
HTTP1.1 |
HTTP2.0 |
|||
HTTP |
HTTP |
HTTPS |
HTTP |
HTTPS |
|
Grafana(Prometheus) |
√ |
||||
Kibana(EFK) |
√ |
||||
Dashboard |
√ |
||||
Harbor |
√ |
||||
API Server |
√(双向认证) |
||||
Etcd |
√(双向认证) |
【资料】
CA证书签发及使用过程:https://www.cnblogs.com/xdyixia/p/11610102.html
HTTPS通信原理:https://www.xinnet.com/xinzhi/63/318224.html
HTTP幂等性概念与应用:https://coolshell.cn/articles/4787.html
Restful与HTTP:https://www.jianshu.com/p/21622d81ab26
HTTP(S)协议概述:https://www.cnblogs.com/zOxygeNz/p/13401497.html