相关概念
URI
URI 包含 URL 和 URN。
==请求和响应报文==
请求报文
响应报文
HTTP方法
- GET:获取资源
- HEAD:获取报文首部
- POST:传输实体主体
- PUT:上传文件(自身不带验证机制,不安全)
- PATCH:对资源进行部分修改(允许部分修改,PUT只能完全替换)
- DELETE:删除文件(不带验证机制)
- OPTIONS:查询支持的方法
- CONNECT:要求在与代理服务器通信时建立隧道(使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。)
- TRACE:追踪路径(不用,容易受到 XST 攻击)
HTTP状态码
链接管理
- 短连接与长连接
长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。
- 从 HTTP/1.1开始默认是长连接的,如果要断开连接,需要由客户端或者服务器端提出断开,使用 Connection : close;
- 在 HTTP/1.1之前默认是短连接的,如果需要使用长连接,则使用 Connection : Keep-Alive。
- 流水线
默认情况下,HTTP请求是按顺序发出的,下一个请求只有在当前请求收到响应之后才会被发出。由于受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。
流水线是在同一条长连接上连续发出请求,而不用等待响应返回,这样可以减少延迟。
Cookie相关
HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。
==Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据==,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)
- 用途
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
- 创建过程
服务器发送的响应报文包含 Set-Cookie 首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 请求首部字段发送给服务器。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
- 分类
- ==会话期 Cookie==:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。
- ==持久性 Cookie==:指定过期时间(Expires)或有效期(max-age)之后就成为了持久性的 Cookie。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Session相关
除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。
==Session 可以存储在服务器上的文件、数据库或者内存中==。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。
使用 Session 维护用户登录状态的过程如下:
- 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
- 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
- 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
- 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。
Cookie 与 Session 选择
- Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选 Session;
- Cookie 存储在浏览器中,容易被恶意查看。Session存在服务器。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密;
- 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。
通信数据转发
- 代理
代理服务器接受客户端的请求,并且转发给其它服务器。
使用代理的主要目的是:
- 缓存
- 负载均衡
- 网络访问控制
- 访问日志记录
代理服务器分为正向代理和反向代理两种:
- 用户察觉得到正向代理的存在。
- 而反向代理一般位于内部网络中,用户察觉不到
- 网关
与代理服务器不同的是,网关服务器会将 HTTP 转化为其它协议进行通信,从而请求其它非 HTTP 服务器的服务。
- 隧道
使用 SSL 等加密手段,在客户端和服务器之间建立一条安全的通信线路。
==HTTPS==
==为什么有HTTP还要HTTPS==?
因为HTTP 有以下安全性问题:
- 使用明文进行通信,内容可能会被窃听;
- 不验证通信方的身份,通信方的身份有可能遭遇伪装;
- 无法证明报文的完整性,报文有可能遭篡改。
==HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信==,也就是说 HTTPS 使用了隧道进行通信。
通过使用 SSL,==HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)==。
加密
- 对称密钥加密
加密和解密使用同一密钥。
- 优点:运算速度快;
- 缺点:==无法安全地将密钥传输给通信方==。
==常见的对称加密算法有:DES、3DES、AES、PBE等==,这几种算法安全行依次递增。
- 非对称密钥加密
又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密钥。
公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。
- 优点:可以更安全地将公开密钥传输给通信发送方;
- 缺点:==运算速度慢==。
==常用的非对称加密算法有RSA和DEA==
- ==HTTPS采用的加密方式==
上面提到对称密钥加密方式的传输效率更高,但是无法安全地将密钥 Secret Key 传输给通信方。而非对称密钥加密方式可以保证传输的安全性,因此我们可以利用非对称密钥加密方式将 Secret Key 传输给通信方。==HTTPS 采用混合的加密机制==,结合两种加密方案:
- 使用非对称密钥加密方式,传输对称密钥加密方式所需要的 Secret Key,从而保证安全性;
- 接收方使用非对称加密方式解密获取到 Secret Key 后,再使用对称密钥加密方式进行通信,从而保证效率。(下图中的 Session Key 就是 Secret Key)
认证
通过使用 证书 来对通信方进行认证。
数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。
服务器的运营人员向 CA 提出公开密钥的申请,CA 在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公开密钥证书后绑定在一起。
进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
完整性保护
SSL 提供报文摘要功能来进行完整性保护。
HTTP 也提供了 MD5 报文摘要功能,但不是安全的。例如报文内容被篡改之后,同时重新计算 MD5 的值,通信接收方是无法意识到发生了篡改。
HTTPS 的报文摘要功能之所以安全,是因为它结合了加密和认证这两个操作。试想一下,加密之后的报文,遭到篡改之后,也很难重新计算报文摘要,因为无法轻易获取明文。
==HTTPS防止中间人劫持==
- 概念:中间人攻击(Man-in-the-middle attack,缩写:MITM)是指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
使用中间人攻击手段,必须要让客户端信任中间人的证书,如果客户端不信任,则这种攻击手段也无法发挥作用。
- 中间人攻击原理
下面我们通过一个流行的MITM开源库mitmproxy来分析中间人攻击的原理。中间人攻击的关键在于https握手过程的ClientKeyExchange,由于pre key交换的时候是使用服务器证书里的公钥进行加密,如果用的伪造证书的公钥,那么中间人就可以解开该密文得到pre_master_secret计算出用于对称加密算法的master_key,从而获取到客户端发送的数据;然后中间人代理工具再使用其和服务端的master_key加密传输给服务端;同样的服务器返回给客户端的数据也是经过中间人解密再加密,于是完整的https中间人攻击过程就形成了,一图胜千言。
- 中间人攻击的三种情况
我们现在常见的SSL中间人攻击方式都是通过伪造、剥离SSL证书来实现的。因为SSL是为网络通信提供安全及数据完整性的一种安全协议,它可以验证参与通讯的一方或双方使用的证书是否由权威受信任的CA机构颁发,并且能执行双向身份认证,几乎不可能会被攻破。
换句话说,如果有SSL中间人攻击事件,并不是SSL协议或者SSL证书的问题,而是SSL证书的验证环节。==中间人攻击的前提条件是,没有严格对证书进行校验,或者人为的信任伪造证书==,因此以下场景正是最容易被用户忽视的证书验证环节:
第 一种:网站并没有部署SSL证书,网站处于HTTP明文传输状态。这种情况黑客可直接通过网络抓包的方式,明文获取传输数据。
第二种:黑客通过伪造SSL证书的方式进行攻击,用户安全意识不强选择继续操作。
第三种:黑客伪造SSL证书,网站/APP只做了部分证书(域名)校验,导致假证书蒙混过关
https://www.cnblogs.com/wh4am1/p/6616856.html
==HTTPS 的缺点==
- 因为需要进行加密解密等过程,因此速度会更慢;
- 需要支付证书授权的高额费用。
HTTP/1.1新特性
- 默认是长连接
- 支持流水线
- 支持同时打开多个 TCP 连接
- 支持虚拟主机
- 新增状态码 100
- 支持分块传输编码
- 新增缓存处理指令 max-age
HTTP/2.0
HTTP/1.x 缺陷
HTTP/1.x 实现简单是以牺牲性能为代价的:
- 客户端需要使用多个连接才能实现并发和缩短延迟;
- 不会压缩请求和响应首部,从而导致不必要的网络流量;
- 不支持有效的资源优先级,致使底层 TCP 连接的利用率低下。
二进制分帧层
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式的。
在通信过程中,只会有一个 TCP 连接存在,它承载了任意数量的双向数据流(Stream)。
- 一个数据流(Stream)都有一个唯一标识符和可选的优先级信息,用于承载双向信息。
- 消息(Message)是与逻辑请求或响应对应的完整的一系列帧。
- 帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。
服务端推送
HTTP/2.0 在客户端请求一个资源时,会把相关的资源一起发送给客户端,客户端就不需要再次发起请求了。例如客户端请求 page.html 页面,服务端就把 script.js 和 style.css 等与之相关的资源一起发给客户端。
首部压缩
HTTP/1.1 的首部带有大量信息,而且每次都要重复发送。
HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见过的首部字段表,从而避免了重复传输。
不仅如此,HTTP/2.0 也使用 Huffman 编码对首部字段进行压缩。
==GET 和 POST 比较==
- 作用:GET 用于获取资源,而 POST 用于传输实体主体。
- 参数:
- GET 的参数是以查询字符串出现在 URL 中,因为 URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。
- POST 的参数存储在实体主体中,POST 参数支持标准字符集。
安全:安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。
GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。
安全的方法除了 GET 之外还有:HEAD、OPTIONS。
不安全的方法除了 POST 之外还有 PUT、DELETE。幂等性:幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。
所有的安全方法也都是幂等的。GET方法是幂等的,POST方法不是。数据长度:GET请求在URL中传送的参数是有长度限制的(不同浏览器不同,2-64kb),而POST没有。
数据包:GET产生一个TCP数据包;POST会产生两个TCP数据包(Firefox不会)。
(对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。)
参考链接:
https://github.com/CyC2018/CS-Notes/blob/master/notes/HTTP.md