Http详解

Published: 10 Apr 2016 Category: 技术

Http请求过程

  • http请求图解 Request

  • DNS URL 和 IP 地址之间的对应由域名解析系统也就是常说的 DNS 来控制。DNS 是一个分布式数据库,把像http://www.google.com 这样的域名翻译成 IP 地址,并将请求映射到远程服务器。 换句话说,DNS 在互联网上记录 URL 和它对应的 IP 地址。所以像 http://www.google.com 这样的域名会被解析成一个 IP 地址197.251.230.45。顺便提一下,通过在浏览器地址栏里敲 IP 地址也能访问网站DNS 数据库被安装在叫做 DNS 服务器的设备上。重要的一点是,DNS服务器集群是分层级的,没有任何一个单一的 DNS 服务器中包含所有数据。如果一个 DNS 服务器里没有一个请求需要的域名,这个 DNS服务器就会把请求转发给这个集群上更上一层节点的 DNS 服务器。最终,这个域名会在某个 DNS 服务器上的数据库里被发现,然后它对应的 IP 地址所代表的设备就会来接受这个请求。 完整的url格式: DNS就是将域名host解析为实际的IP地址:那具体是如何转换的呢? DNS查询首先查找本地缓存,缓存的内容包含两部分,一部分是/etc/hosts文件中的本地绑定,一部分是之前查询过的缓存,这样如果能直接命中的话就不需要再经过一次网络查询,速度会非常快。如果查询不到,就会连接DNS服务器进行查询,这个一般是电信、联通这些ISP的域名服务器,查看/etc/resolve.conf可以看到,当然也可以配置成一些著名的公共DNS,比如:114.114.114.114或者8.8.8.8。现在上网通常是走路由器的,直接拨号上网的情况已很少见了,我们上大学那会儿家庭路由器还不普及才用这种方式。而路由器一般也会做一层DNS的缓存,来避免远程的网络请求。ISP接收到请求后会查询域名服务器,如果当初注册的域名是注册在这里的,那么直接返回结果,如果查询不到向更高一级的域名服务器进行查询请求,直到最顶级的域名服务器。因为域名查询的使用频率非常高,因此每个节点都会做相应的缓存,以便减少不必要的网络开销,但如果域名对应的服务器IP发生了变化,也需要尽早进行刷新,这个缓存的有效期叫TTL,在增加一条A记录进行域名解析时大家可能会注意到这个值,一般默认是10分钟,像DNSPod和阿里云都是这个值。

设置局域网代理上网时,我们一般也会碰到DNS服务器该如何设置的问题,是设置成代理服务器的IP还是ISP的IP?如果通过最简单的IPTABLES的NAT方式来实现局域网代理上网,内网服务器配置的还是ISP的DNS服务器IP,网关需要配置成代理服务器的IP,这样在进行DNS查询时,内网服务器会通过UDP协议连接代理服务器的53端口,通过NAT方式可以将此请求转发到实际的DNS服务器上,从而完成一次DNS查询。

DNS还可以用于服务器的负载匀衡,比如同一个域名可以配置多个IP地址,将DNS的路由方式设置成轮循或者随机,不同客户的请求可以被分配到不同的服务器上, 从而实现一种最简单的集群方案,大网站一般会通过此种方式来实现第一层的负载匀衡,后面才是LVS、Nginx/Apache这些负载匀衡方案

  • Http无状态协议 Http协议本身不对请求和响应之间的通信状态进行保存。也就是说,在http这个协议级别,协议对于发送过的请求或响应都不做持久化处理。目的是为了更快的处理大量事务,确保协议的可伸缩性。随着Web的发展,无状态会导致业务处理变得复杂,因为 HTTP 本质上是个无状态的互联网协议,这就意味着 web 开发人员在构建有状态应用的时候,不得不努力想办法来模拟 web 应用中的有状态体验。举个例子,当你上 Facebook 的时候,你先登录,然后你看到了一个 Facebook 的网页。这就是一个完整的请求/响应周期。你点了一张照片 -- 另一个请求/响应周期 -- 但是在第二个动作之后你并没有退出登录。如果 HTTP 是无状态的,它是怎么维持状态并且知道你刚刚已经登录过了呢? 事实上,如果 HTTP 是无状态的,Facebook 是怎么知道哪个请求是你发出的?它是怎么区分你和其他用户的?这些都是 web 开发人员和 web 开发框架耍的小诡计,让 web 应用看起来像是有状态的。为了实现期望的保持状态功能,后面引入了Cookie技术,后面再详细分析。

  • 各种协议与http协议的关系 请求过程图解enter description here

  • 持久连接节省通信量 在http初始版本,每进行一次http请求就会断开一次tcp连接。持久连接也称为Http keep-alive,其特点是只要一端没有明确提出,则保持TCP连接状态。持久化连接的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务端的负载。另外,减少开销的那部分时间,使http请求和响应能够更早的结束,这样Web页的显示速度也就相应提高了。在HTTP/1.1中,所有的连接默认都是持久连接,而HTTP/1.0内并未标准化。

  • Cookie技术 Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端的状态。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。

  • HTTP报文 大致可以分为报文首部和报文主体两块。两者由最初出现的 空行(CR+LF)来划分。通常,并不一定要有报文主体。

1、压缩传输的内容编码 内容编码指明应用在实体内容上的编码格式,并保持实体信息原样压缩。内容编码后的实体由客户端接收并负责解码。常用的内容编码有以下几种。 gzip(GNU zip) compress(UNIX 系统的标准压缩) deflate(zlib) identity(不进行编码) 2、分割发送的分块传输编码 在 HTTP 通信过程中,请求的编码实体资源尚未全部传输完成之前,浏览器无法显示请求页面。在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。分块传输编码会将实体主体分成多个部分(块)。每一块都会用十六进制来标记块的大小,而实体主体的最后一块会使用“0(CR+LF)”来标记。 3、获取部分内容的范围请求 断点续传,即可恢复机制:能从之前下载中断处恢复下载。指定下载的实体范围。执行范围请求时,会用到首部字段 Range 来指定资源的 byte 范围。 5001~10000字节

Range: bytes=5001-10000

从5001字节之后的全部

Range: bytes=5001-

从一开始到3000字节和5000~7000字节的多重范围

Range: bytes=-3000, 5000-7000

针对范围请求,响应会返回状态码为 206 Partial Content 的响应报文。另外,对于多重范围的范围请求,响应会在首部字段 Content-Type 标明 multipart/byteranges 后返回响应报文。如果服务器端无法响应范围请求,则会返回状态码 200 OK 和完整的实体内容。

4、内容协商返回最合适的内容 内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的基准。包含在请求报文中的某些首部字段(如下)就是判断的基准。Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language

  • HTTP状态码 状态码的类别 类别 原因短语 1XX Informational(信息性状态码) 接收的请求正在处理 2XX Success(成功状态码) 请求正常处理完毕 3XX Redirection(重定向状态码) 需要进行附加操作以完成请求 4XX Client Error(客户端错误状态码) 服务器无法处理请求 5XX Server Error(服务器错误状态码) 服务器处理请求出错 常用的14种: 1、2XX 200 OK 表示从客户端发来的请求在服务器端被正常处理了。 204 No Content 该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体。 一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。 206 Partial Content 该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET 请求。响应报文中包含由 Content-Range指定范围的实体内容。 2、3XX 重定向 301 Moved Permanently 永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后应使用资源现在所指的URI。也就是说,如果已经把资源对应的 URI保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。 像下方给出的请求URI,当指定资源路径的最后忘记添加斜杠“/”,就会产生 301 状态码。 http://example.com/sample 302 Found 临时性重定向。该状态码表示请求的资源已被分配了新的 URI,希望用户(本次)能使用新的 URI 访问。 303 See Other 该状态码表示由于请求对应的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源。 303 状态码和 302 Found 状态码有着相同的功能,但 303 状态码明确表示客户端应当采用 GET 方法获取资源,这点与 302 状态码有区别。 当 301、302、303 响应状态码返回时,几乎所有的浏览器都会把 POST 改成 GET,并删除请求报文内的主体,之后请求会自动再次 发送。301、302 标准是禁止将 POST 方法改变成 GET方法的,但实际使用时大家都会这么做。 304 Not Modified 该状态码表示客户端发送附带条件的请求时,服务器端允许请求访 问资源,但未满足条件的情况,304 状态码返回时,不包含任何响应 的主体部分。304 虽然被划分在 3XX 类别中,但是和重定向没有关 系。(附带条件的请求是指采用 GET 方法的请求报文中包含 If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since 中任一首部。) 3、4XX 客户端错误 400 Bad Request 该状态码表示请求报文中存在语法错误。 401 Unauthorized 该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、 DIGEST 认证)的认证信息。另外若之前已进行过 1次请求,则表示 用户认证失败。 403 Forbidden 该状态码表明对请求资源的访问被服务器拒绝了 404 Not Found 该状态码表明服务器上无法找到请求的资源。 4、5XX 服务器错误 500 Internal Server Error 该状态码表明服务器端在执行请求时发生了错误。 503 Service Unavailable 该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
  • 与HTTP协作的Web服务器 1、用单台虚拟主机实现多个域名 HTTP/1.1 规范允许一台 HTTP 服务器搭建多个 Web 站点。即采用虚拟主机,域名经过DNS解析映射到ip地址,如果一台服务器内托管了比如 www.tricorder.jp 和 www.hackr.jp 这两个域名,那么两者的访问ip地址就会相同,在相同的 IP 地址下,由于虚拟主机可以寄存多个不同主机名和域名的 Web 网站,因此在发送 HTTP 请求时,必须在 Host 首部内完整指定主机名或域名的 URI,这样才能区别不同的请求。 2、通信数据转发程序 :代理、网关、隧道 这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服务器发送的响应再转发给客户端

    代理 代理是一种有转发功能的应用程序,它扮演了位于服务器和客户端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。代理不改变请求 URI,会直接发送给前方持有资源的目标服务器 enter description here在 HTTP 通信过程中,可级联多台代理服务器。请求和响应的转发会经过数台类似锁链一样连接起来的代理服务器。转发时,需要附加Via 首部字段以标记出经过的主机信息。 为何要使用代理?利用缓存技术(稍后讲解)减少网络带宽 的流量,组织内部针对特定网站的访问控制,以获取访问日志为主要目的,等等。 代理按照两种基准分类:一种是是否使用缓存,另一种是是否会修改报文。 缓存代理 代理转发响应时,缓存代理(Caching Proxy)会预先将资源的副本 (缓存)保存在代理服务器上。当代理再次接收到对相同资源的请求时,就可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。 透明代理 转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理(Transparent Proxy)。反之,对报文内容进行加工的代理被称为非透明代理。

    网关 网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客户端可能都不会察觉,自己的通信目标是一个网关。网关能使通信线路上的服务器提供非 HTTP 协议服务。应用场景:利用网关能提高通信的安全性,因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。比如,网关可以连接数据库,使用SQL 语句查询数据。另外,在 Web 购物网站上进行信用卡结算时,网关可以和信用卡结算系统联动。

    隧道 隧道是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方通信连接的应用程序。隧道的目的是确保客户端能与服务器进行安全的通信。隧道本身不会去解析 HTTP 请求。也就是说,请求保持原样中转给之后的服务器。隧道会在通信双方断开连接时结束。其本身是透明的,客户端不用在意。

    前面提到缓存代理服务器可以避免多次从源服务器获取数据,但是代理服务器上的缓存可能会过期,这样就需要保证缓存的有效性。 此外客户端也可以缓存。浏览器缓存如果有效,就不必再向服务器请求相同的资源了,可以直接从本地磁盘内读取。客户端缓存同样存在过期的情况,当判定缓存过期后,也会向源服务器确认资源的有效性。

  • HTTP首部 enter description here enter description here 首部字段: 表 6-1:通用首部字段:请求和响应报文都会使用 首部字段名 说明 Cache-Control 控制缓存的行为 Cache-Control: private, max-age=0, no-cache 使用 no-cache 指令的目的是为了防止从缓存中返回过期的资源。 客户端发送的请求中如果包含no-cache指令,则表示客户端将不会接收缓存过的响应。于是,“中间”的缓存服务器必须把客户端请求转发给源服务器。 如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不能对资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。 当使用 no-store 指令时,暗示请求(和对应的响应)或响应中包含 机密信息。 区别:事实上 no-cache 代表不缓存过期的资源,缓存会向源服务器进行有效期确认后处理资源,也许称为 do-notserve-from-cache-without-revalidation更合适。no-store 才是真正地不进行缓存

    可以使用Cache-Control和实体首部Expires来控制过期日期

    Expires: Fri, 05 Jul 2002, 05:00:00 GMT Cache-Control: max-age=484200

两者的区别在于:Cache-Control首部使用的是相对时间而非绝对日期,所以倾向于使用该首部,绝对日期依赖于计算机始终的正确设置

Connection 逐跳首部、连接的管理
Date 创建报文的日期时间
Pragma 报文指令
Trailer 报文末端的首部一览
Transfer-Encoding 指定报文主体的传输编码方式
Upgrade 升级为其他协议
Via 代理服务器的相关信息
Warning 错误通知
表 6-2:请求首部字段
首部字段名 说明
Accept 用户代理可处理的媒体类型
Accept-Charset 优先的字符集
Accept-Encoding 优先的内容编码
Accept-Language 优先的语言(自然语言)
Authorization Web认证信息
Expect 期待服务器的特定行为
From 用户的电子邮箱地址
Host 请求资源所在服务器
If-Match 比较实体标记(ETag)
If-Modified-Since 比较资源的更新时间
If-None-Match 比较实体标记(与 If-Match 相反)
If-Range 资源未更新时发送实体 Byte 的范围请求
If-Unmodified-Since 比较资源的更新时间(与If-Modified-Since相反)
Max-Forwards 最大传输逐跳数
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中 URI 的原始获取方
TE 传输编码的优先级
User-Agent HTTP 客户端程序的信息
表 6-3:响应首部字段
首部字段名 说明
Accept-Ranges 是否接受字节范围请求
Age 推算资源创建经过时间
ETag 资源的匹配信息
Location 令客户端重定向至指定URI
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次发起请求的时机要求
Server HTTP服务器的安装信息
Vary 代理服务器缓存的管理信息
WWW-Authenticate 服务器对客户端的认证信息
表 6-4:实体首部字段
首部字段名 说明
Allow 资源可支持的HTTP方法
Content-Encoding 实体主体适用的编码方式
Content-Language 实体主体的自然语言
Content-Length 实体主体的大小(单位:字节)
Content-Location 替代对应资源的URI
Content-MD5 实体主体的报文摘要
Content-Range 实体主体的位置范围
Content-Type 实体主体的媒体类型
Expires 实体主体过期的日期时间
Last-Modified 资源的最后修改日期时间
  • 注意点

    1、持久连接

    HTTP持久连接(HTTP persistent connection,也称作HTTP keep-alive或HTTP connection reuse)是使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法。

    可以说http1.1相对于http1.0的最大一个改进就是默认支持http持久连接 在android客户端中如果要关闭持久连接,以http client为例 java request.getHeaders().set("Connection", "close"); 关于持久连接造成EOFException的问题,有待深入了解~ 使用持久连接的优势:

    较少的CPU和内存的使用(由于同时打开的连接的减少了) 允许请求和应答的HTTP管线化 降低网络阻塞 (TCP连接减少了) 减少了后续请求的延迟(无需再进行握手) 报告错误无需关闭TCP连接

    2、断点续传 实际上http的断点续传就是使用的请求首部的Range字段 3、上传文件 4、Last Modified和ETag

  • 关于在浏览器的地址栏输入url发送请求时到底接下来执行了什么?参见博文 1、首先在浏览器的地址栏输入url 2、浏览器根据域名查找相应的ip地址。浏览器会缓存DNS记录一段时间,操作系统不会告诉浏览器DNS记录的存活时间,所以浏览器会缓存他们一个固定的时间,通常根据不同的浏览器会有2到30分钟时间。如果浏览器缓存不包含所需要的记录,浏览器会发送一个系统请求,os也有它自己的缓存。此外,路由器、ISP的DNS服务器都会做缓存,ISP的DNS服务器会从根服务器搜索,通过.com的顶级域名服务器向下遍历查询,直到命中。

    接下来这张图显示了DNS递归查询的: enter description here 对于DNS服务器存在的一个担心就是全部的域名比如 wikipedia.org or facebook.com似乎都映射到了一个ip地址上,这样就存下负载的问题,针对此一般会做如下的处理: a、Round-robin DNS 轮询的方式 即映射多个ip地址,而不是一个 b、负载均衡器 一个硬件设备用于监听一个某一个指定的ip,将请求迁移到其他服务器上,这样可以避免过载,重要的站点一般都会使用高性能的负载均衡器。 c、Geographic DNS 根据客户端的地理位置将域名映射到不同的ip地址 d、Anycast 采用的一种路由选择技术,将一个ip地址映射到多个物理服务器上。但是对于tcp应用的不太好,很少使用~

  • Http的安全威胁以及防范措施 我们知道会话(Session)在维持HTTP的状态上扮演者重要角色,也知道会话id作为一个唯一的令牌来唯一标识一个会话。通常,会话id会作为cookie存储在计算机上的一个随机字符串,会话id会随着每一个到服务器的请求被送往服务器用于唯一标识这个会话。这也是很多web应用的用户认证系统所在做的事,当用户的用户名和密码匹配之后,会话id会存储在用户的浏览器中,这样他们的下一次请求就不需要重新认证了。 但是,如果有一个攻击者拿到了这个会话id,他就会跟用户共享这一个会话,同时也就能访问这个web应用了。 对于会话劫持的对策: 1、重置会话。也就是对于一个用户认证系统来说,一次成功的登录包括验证旧的会话id以及生成一个新的会话id。完成此步骤后,在下一个请求里,会要求受害者进行身份验证。然后会话id就会改变,这样攻击者就无法访问到这个会话了。 2、给会话设置过期时间。这样可以减少攻击者去伪装成一个合法用户的时间,一定程度上缓解攻击。 3、最后一种方式就是整站采用HTTPS把攻击者能够得到的会话id的可能性降到最低。 同源策略 它允许来自同一个站点的资源进行互相访问而不受限制,但是会阻止其他不同站点对文档/资源的访问。也就是说它可以阻止另一个站点通过脚本来操纵本站点的文档。 同源的文档必须有相同的协议,主机名和端口号。举个例子,http://www.test.com/aboutus.html 上的 HTML 文档可以嵌入http://www.test.com/fancy.js 这个 javascript 文件,因为它们是同源的,有相同的协议,主机名和端口号(默认的 80) 。同源策略涉及的是访问文件内容,而不是链接,你可以随意链接到任何 URL。 这样虽然很安全,但是web开发人员可能会需要进行跨域的内容访问, 会很麻烦。但是有了跨域资源共享技术CORS。CORS 是一种机制,允许我们绕过同源策略,从一个域名向另一个域名的资源发起请求。CORS 的原理是添加新的 HTTP 头部,来对一些域名授权,那这些域名就可以发起对本页面资源的请求。 跨站脚本攻击(XSS) 当允许用户输入的HTML和javascript在网站上直接显示时,就可能会受到这种攻击。

  • 关于HTTPS 在讲述HTTPS之前,首先要知道为何要替换掉HTTP,前面也有讲述,主要是防止在数据传输的过程中,所经过的一些网络节点,如WIFI热点、路由器、防火墙、反向代理和缓存服务器等。在HTTP协议下,以百度为例,中间者可以随意嗅探用户搜索的内容,窃取隐私甚至篡改网页。而HTTPS就是为了解决这些问题的。 HTTPS就是在将HTTP报文发送给TCP之前,先将其发送给了一个安全层,对其进行加密。HTTP安全层是通过SSL及其现代替换协议TLS来实现的。参考文献 HTTP和TLS在协议层的位置以及TLS组成如下图: enter description here 可以看到TLS协议主要由5部分组成:应用数据层协议、握手协议、报警协议、加密消息确认协议和心跳协议。TLS 协议本身又是由 record 协议传输的,record协议的格式如上图最右所示。 1、https的作用 内容加密:建立一个信息安全通道,来保证数据传输的安全性 身份认证: 确认网站的真实性,即使被DNS劫持到第三方站点,也能够提醒用户未访问正确服务,可能被劫持 数据完整性:防止数据被第三方冒充或篡改 综上,来看一下HTTP和HTTPS的区别: 1、https协议需要到CA申请证书 2、http是超文本传输协议,信息是明文传输的;https则是具有安全性的ssl加密传输协议 3、http和https使用的是完全不同的连接方式,使用的默认端口也不一样,前者是80,后者是443 4、http的连接时无状态的;而https协议则是由ssl+http协议构建的可进行加密传输、身份认证的网络协议,比http安全 2、https的加密 前面提到,https是对数据的传输过程中的加密,那到底是如何加密的呢?又使用到了哪些加密手段呢? 关于加密以及数字证书详细内容可参考博文。这里只做一个简要的概述: 对称加密:加密和解密数据使用同一把秘钥 非对称加密:加密数据采用的是公钥,解密数据采用的是私钥,两把秘钥是不一样的。两者的关系就是:通过公钥加密的数据,只能通过私钥解开。通过私钥加密的数据,只能通过公钥解开。

    非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是2048位的话,意味着待加密内容不能超过256个字节。

    非对称加密算法强大可靠,但是加解密比较耗时,所以在实际使用中往往与对称加密和摘要算法结合使用。 摘要算法:又称为散列或散列值。就是通过把一个叫做散列算法的单向数学函数应用于数据,将任意长度的一块数据转换为一个定长的、不可逆转的数字,其长度通常在128~256位之间。 摘要算法的特性:1、只要原文本不同,得到的计算结果必然不同(或者说机会很少) 2、无法从结果反推出源数据 常见的摘要算法:MD5、SHA-1、MAC、CRC 摘要算法用于对比信息源是否一致,因为只要源数据发生变化,得到的摘要一定不同。对源数据进行散列处理后得到的数据长度要比源数据短很多,所以称之为摘要。 摘要算法的应用场景:如发件人生成邮件的散列值并加密它,然后将它与邮件本身一起发送。而收件人同时解密邮件和散列值,并由接收到的邮件产生另外一个散列值,然后将两个散列值进行比较。如果两者相同,邮件极有可能在传输期间没有发生任何改变。 数字签名:数字签名技术就是对“非对称密钥加解密”和“数字摘要“两项技术的应用。具体是如何应用的呢?

    假如发送方想把一份报文发送给接收方,在发送报文前,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私人密钥对这个摘要进行加密,这个加密后的摘要将作为报文的”签名“和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公用密钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认报文是从发送方发送且没有被遗漏和修改过!

    更为直观的图文解释可参考博文 该过程中对传送数据生成摘要并使用私钥进行加密的过程就是生成数字签名的过程,而经过加密的数字摘要就是数字签名。

    注意:数字签名只能验证数据的完整性,数据本身是否加密不属于数字签名的控制范围 数字签名有两种功效:一是能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。二是数字签名能确定消息的完整性。

    从上面的分析可以看出,接收方采用发送方的公钥进行数字签名解密,这其中仍然是有风险的,比如如果有恶意用户用自己的公钥替换掉了接收方拿到的公钥,同时恶意用户用自己的私钥做成数字签名,那么接收方就没有办法知道对方不是目标请求者了,很有可能泄露私人信息。于是便引入了下面要讲述的数字证书的机制来保证公钥的可靠性。 这里参考博文:HTTPS科普扫盲帖 以一个比较简单易懂的方式来描述整个加密解密的传输过程 以小明通过浏览器访问某社交网站A为例来说明: 小明在A的登录界面输入账户和密码,点击登录。网站A采用非对称加密,浏览器利用公钥对小明输入的账户信息进行加密,然后将请求发送到服务端,即网站A。然后A采用私钥对加密的数据进行解密,得到登录账户信息,验证通过后,对获取到的小明的社交信息用私钥进行加密,并响应给浏览器,最后浏览器通过公钥解密数据并展示。至此便完成了整个加密解密的请求过程,不过可以发现这里存在两个很明显的问题:1、获取到的小明的社交数据是以私钥的方式加密传输的,而公钥是公开的,也就意味着小明的社交数据是在网络中裸奔的,也就是说这种非对称加密方式只保证了单向数据传输的安全性。2、浏览器是如何获取到前面所说的公钥的呢?下面针对这两个问题分别进行分析: 1、关于单向数据传输的安全性问题,可以结合对称加密的 方式来解决。简而言之,就是采用对称加密的方式对公钥进行加密,具体是如何实现的呢?下面仍然以小明访问社交网站A为例来说明: 小明访问A,A将自己的证书给到小明(实际上是发送给浏览器,小明是未感知的);浏览器从证书中取到公钥a;浏览器生成一个只有自己知道的对称秘钥b,并用公钥a进行加密,接着传送给A(这个中间会有协商的过程,暂时这里简化);A通过私钥解密,拿到对称密钥b;这之后浏览器和A之间的数据传输都采用秘钥b进行加密。 附上流程图(原图来源enter description here 2、关于公钥的获取,涉及到两个概念:数字证书以及签发机构CA。简单说就是访问网站是会得到一个证书,证书中会包含公钥,这些证书是由CA来签发的,所以这里就存在一个问题就是证书的安全性问题,那如何来确保呢?一般而言CA的权威性可以保证一定程度上的安全性,但是证书依然有可能被伪造或篡改。举例来说,如果小明在登录授权服务器之前,路由转发的过程中请求先到了代理服务器,假如此时代理服务器被入侵,那么将小明的请求拦截掉,并返回一个非法证书,如果相信了该证书,那么小明的私人信息仍然会在网络中裸奔,但实际情况肯定不会这样,那具体又是如何处理这种情况的呢? 这里就要提到数字证书了,那究竟数字证书扮演着什么角色呢?对于请求方而言,如何确定所得到的数字证书中的公钥就是目标主机返回的呢?是不是被篡改过呢? 这时,我们就需要一个权威的值得信赖的第三方机构(一般是由政府审核并授权的机构)来统一对外发放主机机构的公钥,只要请求方这种机构获取公钥,就避免了上述问题的发生。这种机构被称为证书权威机构(Certificate Authority, CA),它们所发放的包含主机机构名称、公钥在内的文件就是人们所说的“数字证书”。那数字证书如何发放呢?可参考百度百科:

    用户首先产生自己的密钥对,并将公共密钥及部分个人身份信息传送给认证中心。认证中心在核实身份后,将执行一些必要的步骤,以确信请求确实由用户发送而来,然后,认证中心将发给用户一个数字证书,该证书内包含用户的个人信息和他的公钥信息,同时还附有认证中心的签名信息。用户就可以使用自己的数字证书进行相关的各种活动。数字证书由独立的证书发行机构发布。数字证书各不相同,每种证书可提供不同级别的可信度。可以从证书发行机构获得您自己的数字证书。

    这里有几个点要说明一下:首先用户发送相关信息到认证中心进行认证,其真实性是由认证中心来确认的,用户无需关心,当认证通过后会发送证书。然后,证书中包含他自身的公钥,这个不需要关心被篡改,因为当浏览器收到证书后会采用这个公钥进行解密摘要信息(摘要信息是用私钥加密的),如果被篡改,将是无法解密的,所以用户也无需担心。

    证书包含哪些内容:1、证书颁发机构的名称 2、证书本身的数字签名 3、证书持有者公钥 4、证书签名用到的Hash算法 证书的有效性验证浏览器默认都会内置CA根证书,其中根证书包含了CA的公钥 1、证书颁发的机构是伪造的:浏览器不认识(浏览器默认会预装很多签名机构的证书),直接认为是危险证书 2、证书颁发的机构是确实存在的,于是根据CA名,找到对应内置的CA根证书、CA的公钥。用CA的公钥,对伪造的证书的摘要进行解密,发现解不了,认为是危险证书。 3、对于篡改的证书,使用CA的公钥对数字签名进行解密得到摘要A,然后再根据签名的Hash算法计算出证书的摘要B,对比A与B,若相等则正常,若不相等则是被篡改过的。 4、证书可在其过期前被吊销,通常情况是该证书的私钥已经失密。较新的浏览器如Chrome、Firefox、Opera和Internet Explorer都实现了在线证书状态协议(OCSP)以排除这种情形:浏览器将网站提供的证书的序列号通过OCSP发送给证书颁发机构,后者会告诉浏览器证书是否还是有效的。

    1、2点是对伪造证书进行的,3是对于篡改后的证书验证,4是对于过期失效的验证。

    接下来就详细来描述SSL/TLS的握手过程:这里参考博文详解https是如何保证安全的,整个握手的过程如下图所示 enter description here 客户端首次发出请求

    由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在TLS握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret 。

    客户端需要提供如下信息:

    1、支持的协议版本,比如TLS 1.0版 2、一个客户端生成的随机数,稍后用于生成”对话密钥” 3、支持的加密方法,比如RSA公钥加密 4、支持的压缩方法 5、服务端首次回应

    服务端在接收到客户端的Client Hello之后,服务端需要确定加密协议的版本,以及加密的算法,然后也生成一个随机数,以及将自己的证书发送给客户端一并发送给客户端,这里的随机数是整个过程的第二个随机数。

    服务端需要提供的信息:

    1、协议的版本 2、加密的算法 3、随机数 4、服务器证书 5、客户端再次回应

    客户端首先会对服务器下发的证书进行验证,验证通过之后,则会继续下面的操作,客户端再次产生一个随机数(第三个随机数),然后使用服务器证书中的公钥进行加密,以及放一个ChangeCipherSpec消息即编码改变的消息,还有整个前面所有消息的hash值,进行服务器验证,然后用新秘钥加密一段数据一并发送到服务器,确保正式通信前无误。 客户端使用前面的两个随机数以及刚刚新生成的新随机数,使用与服务器确定的加密算法,生成一个Session Secret。

    ChangeCipherSpec ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了。

    服务器再次响应

    服务端在接收到客户端传过来的第三个随机数的 加密数据之后,使用私钥对这段加密数据进行解密,并对数据进行验证,也会使用跟客户端同样的方式生成秘钥,一切准备好之后,也会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了。之后,服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。

    后续客户端与服务器间通信

    确定秘钥之后,服务器与客户端之间就会通过商定的秘钥加密消息了,进行通讯了。整个握手过程也就基本完成了。

    值得特别提出的是: SSL协议在握手阶段使用的是非对称加密,在传输阶段使用的是对称加密,也就是说在SSL上传送的数据是使用对称密钥加密的!因为非对称加密的速度缓慢,耗费资源。其实当客户端和主机使用非对称加密方式建立连接后,客户端和主机已经决定好了在传输过程使用的对称加密算法和关键的对称加密密钥,由于这个过程本身是安全可靠的,也即对称加密密钥是不可能被窃取盗用的,因此,保证了在传输过程中对数据进行对称加密也是安全可靠的,因为除了客户端和主机之外,不可能有第三方窃取并解密出对称加密密钥!如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。

    其他补充

    对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。

    PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在Client Hello阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。

    session的恢复 有两种方法可以恢复原来的session:一种叫做session ID,另一种叫做session ticket。

    session ID

    session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的”对话密钥”,而不必重新生成一把。

    session ID是目前所有浏览器都支持的方法,但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话

    session ticket

    客户端发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。

    目前只有Firefox和Chrome浏览器支持。

    总结 https实际就是在TCP层与http层之间加入了SSL/TLS来为上层的安全保驾护航,主要用到对称加密、非对称加密、证书,等技术进行客户端与服务器的数据加密传输,最终达到保证整个通信的安全性。

    需注意的是:通过上面的分析可以知道,SSL协议在握手阶段使用的是非对称加密,在传输阶段使用对称加密,也就是说在安全层SSL上传送的数据是使用对称加密的。因为非对称加密的速度缓慢,耗费资源。

  • 关于Session、Cookie和Token的区别

  • 关于http2.0

  • HTTPS的一些误解 参考阮一峰博文 1、HTTPS无法缓存:很多人认为,处于安全考虑,浏览器不会在本地保存HTTPS缓存。实际上,只要HTTP头中使用特定命令,HTTPS是可以缓存的。引用微软项目经理的话:

    "说来也许令人震惊,只要HTTP头允许这样做,所有版本的IE都缓存HTTPS内容。比如,如果头命令是Cache-Control: max-age=600,那么这个网页就将被IE缓存10分钟。IE的缓存策略,与是否使用HTTPS协议无关。(其他浏览器在这方面的行为不一致,取决于你使用的版本,所以这里不加以讨论。)"

    Firefox默认只在内存中缓存HTTPS。但是,只要头命令中有Cache-Control:Public,缓存就会被写到硬盘上。下面的图片显示,Firefox的硬盘缓存中有HTTPS内容,头命令正是Cache-Control:Public。 2、HTTPS太慢:实际上因为增加了安全层的加密验证机制,可能会增加网络请求的一些开销,但是可以通过一些技巧来大大减少这些开销。 3、只有注册登录页才需要HTTPS:其实劫持他人的session是很容易的。

参考文献: 数字证书的基础知识 HTTPS科普扫盲帖 和安全有关的那些事 OpenSSL 与 SSL 数字证书概念贴 基于OpenSSL自建CA和颁发SSL证书 聊聊HTTPS和SSL/TLS协议 SSL/TLS协议运行机制的概述 图解SSL/TLS协议 大型网站的 HTTPS 实践 SSL/TLS原理详解 扒一扒HTTPS网站的内幕 白话解释 OSI模型,TLS/SSL 及 HTTPS OpenSSL HeartBleed漏洞原理漫画图解 百度全站 https 技术宅告诉你如何搜索更安全

comments powered by Disqus

About me

面朝大海,春暖花开。哈喽,大家好,我是Randy!