Https TLS/SSL 通信原理

为什么需要Https

HTTP协议存在的问题

  • HTTP报文使用明文(指未经过加密的报文)方式发送
  • 无法证明报文的完整性,所以可能遭篡改
  • 不验证通信方的身份,因此有可能遭遇伪装

Https优势

  • 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
  • 数据完整性:内容传输经过完整性校验
  • 身份认证:第三方无法伪造服务端(客户端)身份

    TLS/SSL原理

    通过非对称加密来进行身份认证和密钥协商,对称加密的算法采用协商的密钥对数据加密,使用散列函数验证数据完整性

    对称加密

    加密和解密使用同一把密钥,没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了

    非对称加密

    公钥加密只能私钥解密,私钥加密只能公钥解密。
    一把公钥,一把私钥。公钥可以任意发布,私钥自己保存,使用公钥加密的信息只有私钥能解密。特点是一对多
    缺点:

  • 公钥是公开的,所以针对私钥加密的信息,黑客截获后可以使用公钥进行解密,获取其中的内容;

  • 公钥并不包含服务器的信息,使用非对称加密算法无法确保服务器身份的合法性,存在中间人攻击的风险,服务器发送给客户端的公钥可能在传送过程中被中间人截获并篡改;
  • 使用非对称加密在数据加密解密过程需要消耗一定时间,降低了数据传输效率;

    对称加密+非对称加密(HTTPS采用这种方式)

    服务器生成非对称加密密钥对,分发公钥给客户端。
    客户端生成对称加密密钥,用服务器的非对称加密公钥加密传输,然后服务器用私钥解密对称加密的公钥

    数字签名(防止数据篡改)

    发送者:将一段文本先用Hash函数生成消息摘要,然后用发送者的私钥加密生成数字签名,与原文文一起传送给接收者。
    接收者:接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与上一步得到的摘要信息对比。
    问题:公钥可伪造

    CA证书

    数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上。

  • 服务器的运营人员向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;

  • CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
  • 如信息审核通过,CA会向申请者签发认证文件-证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名。 其中签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA的私钥对信息摘要进行加密,密文即签名;
  • 客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件;
  • 客户端 Client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即服务器的公开密钥是值得信赖的。
  • 客户端还会验证证书相关的域名信息、有效时间等信息; 客户端会内置信任CA的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA的证书,证书也会被判定非法。

    通信过程

    1.Client发起一个HTTPS(比如https://juejin.cn/user/4283353031252967)的请求,根据RFC2818的规定,Client知道需要连接Server的443(默认)端口。
    2.Server把事先配置好的公钥证书(public key certificate)返回给客户端。
    3.Client验证公钥证书:比如是否在有效期内,证书的用途是不是匹配Client请求的站点,是不是在CRL吊销列表里面,它的上一级证书是否有效,这是一个递归的过程,直到验证到根证书(操作系统内置的Root证书或者Client内置的Root证书)。如果验证通过则继续,不通过则显示警告信息
    4.Client使用伪随机数生成器生成加密所使用的对称密钥然后用证书的公钥加密这个对称密钥,发给Server。
    5.Server使用自己的私钥(private key)解密这个消息,得到对称密钥。至此,Client和Server双方都持有了相同的对称密钥。
    6.Server使用对称密钥加密“明文内容A”,发送给Client。
    7.Client使用对称密钥解密响应的密文,得到“明文内容A”。
    8.Client再次发起HTTPS的请求,使用对称密钥加密请求的“明文内容B”,然后Server使用对称密钥解密密文,得到“明文内容B”。

证书被劫持怎么办?

证书被修改:黑客使用电脑内置密钥可以解密证书,但是无法加密证书里面的内容,加密方式不对会导致A无法解密。强行修改证书会导致签名也修改,导致最终A比对签名时不一致。
证书被替换:证书中有发送端(B)的IP网址,如果替换,会导致IP网址不一样,A比对自己请求IP

HTTP 与 HTTPS 的区别

  • HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO,谷歌、百度优先索引HTTPS网页;
  • HTTPS需要用到SSL证书,而HTTP不用;
  • HTTPS标准端口443,HTTP标准端口80;
  • HTTPS基于传输层,HTTP基于应用层;
  • HTTPS在浏览器显示绿色安全锁,HTTP没有显示;

    Http2

浏览器缓存

储存位置

Service Worker
Service Worker 是运行在浏览器背后的独立线程,即让JS 运行在主线程之外,由于它脱离了浏览器的窗体,因此无法直接访问到Dom。但仍可以帮我们完成很多功能。 一般可以用来实现缓存功能。使用Service Worker的话,传输协议必须为Https。因为Service Worker 中涉及到请求拦截,所以必须使用HTTPS来保障安全。Service的缓存与浏览器其它内建缓存机制不同。它可以t让我们自由的控制缓存哪些文件、如何匹配缓存、如何读取缓存、并且缓存时持续性的。
Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册Service Worker,然后监听到install 事件后就可以缓存需要的文件,那么在用户下次访问时就可以通过拦截请求的方式来查询缓存是否存在,存在的话就直接读取缓存,否则的话就去请求数据
memory cache
内存中缓存的数据读取高效但缓存的持续性短,会随着进程的释放而释放。一旦我们关闭tab页,内存中的缓存也被释放了。
将资源缓存在内存中,下次访问直接直接从内存中拿。Webkit内核只缓存派生资源(如HTML内嵌的图片和脚本链接),对应的类为CachedResource
disk cache
Disk Cache 也就是存储在硬盘中的缓存,虽然读取速度慢,但是什么都能存储到磁盘中,在存储容量和时效性上都要超过Memory Cache
它会根据HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期要重新请求
image.png
像CSS基本加载一次就不需要再去动它,所以适合放在磁盘中,而我们的JS脚本需要经常运行,所以不适合放在磁盘中,因为会有大量IO开销
push cache
Push Cash(推送缓存)是HTTP/2中的内容,当以上三种缓存都没有命中时,它才会被使用。<它只在会话(Session)中存在,一旦会话结束就会被释放,并且缓存时间也很短暂,在chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

三级缓存原理(缓存访问优先级)

1、先从内存中找,找到就直接使用
2、内存中没有去磁盘中找,找到直接使用
3、磁盘中没有,就直接去请求资源
4、请求完将资源缓存在内存和磁盘上

强缓存

http1.0时代,用的是:Expires:绝对时间,当服务器和客户端时间偏差大,会导致缓存错乱。
http1.1之后,用header中的Cache-Control字段,通过Cache-Control:max-age=3600来设置有效时间为3600秒,是一个相对时间。
Cache-Control除了max-age之外,还有:
no-cache:跳过当前的强缓存,发送HTTP请求,即直接进入协商缓存阶段。
no-store:禁止使用缓存,
public:资源允许被中间服务器缓存
private:只能被终端用户的浏览器缓存,资源不允许被中间代理服务器缓存。
Cache-Control 和Expires 可同时使用,Cache-Contorl优先度高。

协商缓存

强缓存没有命中,会发送一个请求到到服务器,服务器根据header中的信息,来判断是否命中缓存,命中的话,返回304,告诉浏览器资源未更新,可以直接使用缓存数据。
这里header中的信息是指:Last-Modify/If-Modify-Since 和 ETag/If-None-Match.
Last-Modify/If-Modify-Since
浏览器第一次请求服务器时,会在返回heder中加上 Last-Modify 值为资源最近更改的时间。
之后浏览器再请求服务器时,请求头中会添加 If-Modify-Since ,值为Last-Modify的值,服务器收到后会比较时间是否一致来判断资源是否有修改。
缺点:如果服务器资源周期性变化,变了一圈之后会恢复最初的样子,这样我们其实是可以使用缓存的,但是记录更新时间这种方式做不了
Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。
编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。

ETag/If-None-Match
ETag 是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变。服务器通过响应头把这个值给浏览器。
浏览器接收到ETag的值,会在下次请求时,将这个值作为If-None-Match这个字段的内容,并放到请求头中,然后发给服务器。
服务器接收到If-None-Match后,会跟服务器上该资源的ETag进行比对:

  • 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
  • 否则返回304,告诉浏览器直接用缓存。

跨域

同源策略

「同源策略」是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
只有当
「protocol(协议)、domain(域名)、port(端口)三者一致。」
才是同源

CORS(跨域资源共享)

浏览器会自动进行CORS通信,实现CORS通信主要在服务端。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS,该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
简单请求

  • 条件1:使用下列方法之一:
  • GET
  • HEAD
  • POST

条件2:Content-Type 的值仅限于下列三者之一:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

前端发送简单请求正常请求即可

复杂请求
非简单请求会发出一次预检请求,返回码是204,预检测通过才会真正发出请求,这才返回200。
这里通过前端发请求的时候增加一个额外的headers来触发非简单请求。

  1. fetch(`http://localhost:9871/api/cors?msg=helloCors`, {
  2. // 需要带上cookie
  3. credentials: 'include',
  4. // 这里添加额外的headers来触发非简单请求
  5. headers: {
  6. 't': 'extra headers'
  7. }
  8. }).then(res => {
  9. console.log(res)
  10. })

JSONP

原理:在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的
缺点:只能发送get请求

form表单

跨域实际上请求发出去了,只是因为同源策略未返回,而form表单属于‘写数据’,只需要将数据发送出去即可。

postMessage

H5新的API,是可以跨域操作的windowsApi

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

otherWindow.postMessage(message, targetOrigin, [transfer]);
通过postMessage来发送数据,通过onMessage来接收数据

  1. http://localhost:3000/a.html
  2. <iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe> //等它加载完触发一个事件
  3. <script>
  4. function load() {
  5. let frame = document.getElementById('frame')
  6. frame.contentWindow.postMessage('我爱你', 'http://localhost:4000') //发送数据
  7. window.onmessage = function(e) { //接受返回数据
  8. console.log(e.data) //我不爱你
  9. }
  10. }
  11. </script>
  1. http://localhost:4000/b.html
  2. // b.html
  3. window.onmessage = function(e) {
  4. console.log(e.data) //我爱你
  5. e.source.postMessage('我不爱你', e.origin)
  6. }

状态码

1xx 接收请求正在处理
2xx 请求正常处理完毕
3xx 重定向
4xx 客户端出错
5xx 服务器出错

100 continue 继续请求
101 switching protocols 切换请求协议

200 ok正常处理请求
204 nocontent 服务器成功处理 但无内容返回

301 Moved Permanently 永久重定向,原资源已经删除
302 found 临时重定向 如http转https

400 bad request 请求报文语法错误
401 unauthorized 需要登陆验证身份
403 forbidden 拒绝请求
404 not fund 无法找到请求资源

500 服务器执行请求发生错误
503 服务器停机

XSS攻击

XSS 攻击是指浏览器中执行恶意脚本(无论是跨域还是同域),从而拿到用户的信息并进行操作。
会造成以下影响:

  1. 窃取Cookie。
  2. 监听用户行为,比如输入账号密码后直接发送到黑客服务器。
  3. 修改 DOM 伪造登录表单。
  4. 在页面中生成浮窗广告。

    存储型

    通过恶意方式将脚本注入服务器,之后服务器将脚本发送给客户端会自动执行。
    常见的场景是留言评论区提交一段脚本代码,如果前后端没有做好转义的工作,那评论内容存到了数据库,在页面渲染过程中直接执行, 相当于执行一段未知逻辑的 JS 代码。

    反射型

    通过请求参数的形式将脚本注入服务器,之后再返回浏览器。

[http://sanyuan.com?q=<script>alert("](http://sanyuan.com?q=<script>alert(")你完蛋了")</script>
比如这个q参数为[<script>alert("](http://sanyuan.com?q=<script>alert(")你完蛋了")</script> 一段脚本,
之后将此脚本返回给客户端即会被攻击。
之所以叫它反射型, 是因为恶意脚本是通过作为网络请求的参数,经过服务器,然后再反射到HTML文档中,执行解析。和存储型不一样的是,服务器并不会存储这些恶意脚本。

文档型

文档型的 XSS 攻击并不会经过服务端,而是作为中间人的角色,在数据传输过程劫持到网络数据包,然后修改里面的 html 文档
这样的劫持方式包括WIFI路由器劫持或者本地恶意软件等。

防范措施

  1. 不要相信用户输入的内容,要对用户内容进行转码

    1. <script>alert('你完蛋了')</script>

    转码为

    1. &lt;script&gt;alert(&#39;你完蛋了&#39;)&lt;/script&gt;

    这样的代码在 html 解析的过程中是无法执行的。
    当然也可以利用关键词过滤的方式,将 script 标签给删除。

  2. CSP,即浏览器中的内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源,具体来说可以完成以下功能:

  • 限制其他域下的资源加载
  • 禁止向其它域提交数据
  • 提供上报机制,能帮助我们及时发现 XSS 攻击
  1. Http Only

很多 XSS 攻击脚本都是用来窃取Cookie, 而设置 Cookie 的 HttpOnly 属性后,JavaScript 便无法读取 Cookie 的值。这样也能很好的防范 XSS 攻击。

CSRF攻击

CSRF(Cross-site request forgery), 即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求
在正常网站中,黑客会诱导点击链接,之后会将你在正常网站的cookie携带,去自动发送get /post 请求,因为携带了相应的cookie信息,服务器会认为你是正常用户。
防范措施

利用Cookie的SameSite属性

SameSite可以设置为三个值,Strict、Lax和None。
a. 在Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com网站只能在sanyuan.com域名当中请求才能携带 Cookie,在其他网站请求都不能。
b. 在Lax模式,就宽松一点了,但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。
c. 在None模式下,也就是默认模式,请求会自动携带上 Cookie。

CSRF Token

首先,浏览器向服务器发送请求时,服务器生成一个字符串,将其植入到返回的页面中。
然后浏览器如果要发送请求,就必须带上这个字符串,然后服务器来验证是否合法,如果不合法则不予响应。这个字符串也就是CSRF Token,通常第三方站点无法拿到这个 token, 因此也就是被服务器给拒绝。

验证来源站点

这就需要要用到请求头中的两个字段: OriginReferer
其中,Origin只包含域名信息,而Referer包含了具体的 URL 路径。
当然,这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。

预检请求

HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为”*”)使用该方法。
简单来说,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。

options 关键的请求头字段

request header 的关键字段
image.png
如:

  1. Access-Control-Request-Method: POST
  2. Access-Control-Request-Headers: X-PINGOTHER, Content-Type

response header 的关键字段
image.png

预检请求优化

1、使用简单请求
2、使用 Access-Control-Max-Age设置缓存时间

TCP/IP

TCP/IP协议族

应用层
应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。
运行在TCP上:HTTP/HTTPS FTP(文件传输) SMTP(简单邮件传输协议)
运行在UDP上:

  • BOOTP(Boot Protocol,启动协议),应用于无盘设备。
  • NTP(Network Time Protocol,网络时间协议),用于网络同步。
  • DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),动态配置IP地址。

运行在TCP和UDP上:
DNS(域名解析)

传输层(TCP/UDP)

UDP:

  1. 面向无连接。不需要三次握手建立连接,不会对数据拆分和拼接。
  2. 有单播、多播、广播功能。UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。
  3. 面向报文。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文
  4. 不可靠性。想发即发(不需建立连接)、不会确认对方是否正确接收到数据、无阻塞控制(UDP会以恒定的速度发送数据,即使网络不好会造成丢包,优点是对实时性要求高的场景适用,比如视频会议等。)
  5. 首部开销小,只有8个子节,TCP至少20子节,最大60子节

TCP:

  1. 面向连接。发送数据之前通过三次握手建立连接。
  2. 仅支持单向传播。每条TCP传输连接只能有两个端点,只能进行点对点的数据传输,不支持多播和广播传输方式。
  3. 面向子节流。TCP不像UDP一样那样一个个报文独立地传输,而是在不保留报文边界的情况下以字节流方式进行传输。
  4. 可靠传输。TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
  5. 阻塞控制。当网络出现拥塞的时候,TCP能够减小向网络注入数据的速率和数量,缓解拥塞
  6. 双工通信。TCP允许通信双方的应用程序在任何时候都能发送数据,因为TCP连接的两端都设有缓存,用来临时存放双向通信的数据。

    网络层

    寻找合适的网间路由和交换节点,确保计算机通信能及时传送。

    数据链路层

    在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。