OSI 7 层模型

  1. 应用层
  2. 表示层
  3. 会话层
  4. 传输层
  5. 网络层
  6. 数据链路层
  7. 物理层

辅助记忆:物数网传会表应(误上网站会屌硬)

TCP/IP 协议

客户端与服务器端进行相互通信,双方必须遵循相同的规则,比如:

  1. 如何探测到通信目标
  2. 由哪一边先发起通信
  3. 使用哪种语言进行通信
  4. 怎样结束通信
  5. 不同的硬件、操作系统之间如何通信

而这一切都需要一种特定的规则来约束,我们称该规则为 协议。

TCP/IP 协议是一个协议集合。TCP/IP 协议按照层次分为以下五层。

  1. 应用层(HTTP 协议,FTP 协议,DNS 协议)
  2. 传输层(TCP 协议,UDP 协议)
  3. 网络层(IP 协议)
  4. 数据链路层
  5. 物理层

发送端在层与层间传输数据时,每经过一层都会被加上首部信息,接收端每经过一层都会删除一条首部

  1. 应用层–> http 数据
  2. 传输层–> http 数据 + TCP 首部
  3. 网络层–> http 数据 + TCP 首部 + IP 首部
  4. 数据链路层–> http 数据 + TCP 首部 + IP 首部 + 以外网首部

HTTP 协议

HTTP 是超文本传输协议,是应用层协议,是无状态的,通过 session 和 cookie 来保持会话状态。包含请求报文和响应报文。基于 TCP 协议。

TCP, UDP 协议

UDP:用户数据报协议,是一个简单的面向数据报的传输层协议。
是不可靠的传输协议,在传输数据之前不需要先建立连接,在接收到 UDP 报文后,不需要确认。只要有数据就发,不管对方是否可以正确接受。优点,无需建立连接,效率高,头部小。

使用场景有:音视频传输,直播,动作类游戏等(常说的丢包)。

TCP:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
通过三次握手建立连接,四次挥手取消连接,因为 TCP 是全双工的,因此在每一个方向都必须单独关闭。

区别:

  1. TCP 提供面向连接的传输,通信前要先建立连接(三次握手机制);UDP 提供无连接的传输,通信前不需要建立连接。
  2. TCP 提供可靠的传输(有序,无差错,不丢失,不重复); UDP 提供不可靠的传输。
  3. TCP 面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组; UDP 是面向数据报的传输,没有分组开销。
  4. TCP 提供拥塞控制和流量控制机制; UDP 不提供拥塞控制和流量控制机制。

TCP 三次握手,四次挥手

SYN(Synchronize):请求连接
ACK(Acknowledgement):确认
FIN(Finish):请求关闭连接

三次握手:

  1. 主机 A:SYN
  2. 主机 B:SYN+ACK
  3. 主机 A:ACK

四次挥手:

  1. 主机 A:FIN
  2. 主机 B:ACK
  3. 主机 B:FIN
  4. 主机 A:ACK

请求报文,响应报文

请求报文:

  1. 请求行
    请求方法字段、URL 字段、HTTP 协议版本字段。它们用空格分隔。例如 GET /index.html HTTP/1.1
  2. 请求头
    请求头由关键字/值对组成,每对占一行。
  3. 空行
  4. 请求体
    请求携带的数据。

响应报文:

  1. 响应行
    包含协议版本,状态码和状态码的原因短语,例如:HTTP/1.1 200 OK
  2. 响应头
    请求头也是由关键字/值对组成,每对占一行。
  3. 空行
  4. 响应体
    服务器响应的数据

HTTPs

http 协议的数据都是明文进行传输的,所以对于一些敏感信息的传输就很不安全,HTTPS 就是为了解决 HTTP 的不安全而生的。

对称加密:即通信的双方都使用同一个秘钥进行加解密。
非对称加密:用一对密钥对,公钥加私钥。用私钥加密的数据,只有对应的公钥才能解密,用公钥加密的数据,只有对应的私钥才能解密。

对称加密虽然很简单性能也好,但是无法解决首次把秘钥发给对方的问题,很容易被黑客拦截秘钥。
非对称加密虽然安全性更高,但是带来的问题就是速度很慢,影响性能。
那么结合两种加密方式,将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

如果此时在客户端和服务器之间存在一个中间人,这个中间人只需要把原本双方通信互发的公钥,换成自己的公钥,这样中间人就可以轻松解密通信双方所发送的所有数据。
要保证数据的安全,就必须得保证服务器给客户端下发的公钥是真正的公钥,而不是中间人伪造的公钥。那就得引入数字证书了,数字证书是服务器主动去权威机构申请的,证书中包括:签发者、证书用途、使用者公钥、使用者的 HASH 算法、证书到期时间等。
证书中的公钥,是权威机构的私钥加密的,而权威机构的私钥是内置在浏览器或操作系统环境中的。
客户端收到权威机构的证书之后,用内置的私钥解密得到服务端公钥,进行操作。

但是如果证书被中间人篡改了,那样客户端拿到的公钥还是中间人的。所以还要保证客户端收到的证书是服务器下发的证书,没有被中间人篡改过。
数字签名正是这个作用。证书中包含该证书的数字签名(权威机构通过 hash 算法生成证书的数字摘要,然后用私钥加密,得到数字签名)

数字签名怎么防止证书被篡改?

  1. 客户端接收到证书以后,用内置的私钥解密得到服务端公钥和证书签名,再将签名解密得到数字摘要,用同样的算法计算数字摘要,两者如果一致,说明证书没有被串改。
  2. 如过证书被调包,上面的签名肯定是没有问题的,但是客户端还会检查证书中的域名和当前访问的域名是否一致。如果不一致,会发出警告!

https 通信过程:

  1. 客户端发起 https 请求
  2. 服务端下发证书
  3. 客户端验证证书,并获得服务端公钥
  4. 客户端生成一个随机的对称密钥,用服务端公钥加密
  5. 服务端用自己的私钥解密,得到对称加密的密钥
  6. 双方用对称加密进行通信

HTTP1.0、HTTP1.1 和 HTTP2.0 的区别

HTTP1.0 最早在网页中使用是在 1996 年,HTTP1.1 则在 1999 年才开始广泛应用,也是当前使用最为广泛的 HTTP 协议。HTTP2.0 是在 2015 年产生。HTTP 协议的升级其实是对 HTTP 进行深入理解并不断优化的过程。主要为了优化带宽和延迟。

HTTP1.0 HTTP 1.1 主要区别

  1. 请求方法和状态码
    HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
    HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
    还新增了一些状态码。
  2. 长连接
    HTTP 1.0 规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个 TCP 连接,服务器完成请求处理后立即断开 TCP 连接。
    在 HTTP/1.1 中,一个连接可用于一次或多次请求/响应交换,尽管连接可能由于各种原因被关闭。
    要建立长连接,可以在请求消息中包含 Connection: Keep-Alive 头,如果服务器愿意维持这条连接,在响应消息中也会包含一个 Connection: Keep-Alive 的头。请求头中如果 Connection: false,表示此次请求结束后关闭长连接。
    HTTP1.1 默认添加这个头部,HTTP1.0 需要手动添加。
  3. 缓存处理
    在 HTTP1.0 中主要使用 header 里的 Expires, If-Modified-Since/Last-Modefied 来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如:Cache-Control, Etag/If-None-Match 等更多可供选择的缓存头来控制缓存策略。
  4. Host 域
    HTTP1.1 在请求头里多了一个 Host 域,而且是必传的,HTTP1.0 则没有这个域。请求消息中如果没有 Host 域会报 400。
  5. 带宽优化及网络连接的使用
    HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

HTTP1.1 与 HTTP2.0 的区别

  1. 二进制分帧
    HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。
    HTTP/1 的请求和响应报文,都是由起始行,头部和实体正文(可选)组成,各部分之间以文本换行符分隔。
    HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
  2. 头部压缩
    HTTP/1.x 会在请求和响应中中重复地携带不常改变的、冗长的头部数据,给网络带来额外的负担。
    HTTP/2 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送。只发送差异数据。
  3. 服务端推送
    服务端可以在发送页面 HTML 时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。
    服务端可以主动推送,客户端也有权利选择接收与否。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。
  4. 多路复用
    HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8 个(Chrome 是 6 个)的 TCP 链接请求限制。
    HTTP2 中,所有的请求都是通过一个 TCP 连接并发完成。
    同域名下所有通信都在单个连接上完成。
    单个连接可以承载任意数量的双向数据流。
    数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

    多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。http2.0 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。

  5. HTTP2.0 要基于 HTTPs

SSE(Server-Sent Event,服务端推送事件)

服务器推送事件(Server-sent Events)是基于 WebSocket 协议的一种服务器向客户端发送事件&数据的单向通讯。一般用在服务器主动向客户端通信,而客户端无需与服务端通信的时候。如果双向交互,可以用 websocket,因为他是全双工的。也可以用轮询,但是浪费资源。

在 Web 应用程序中使用服务器发推送件很简单。在服务器端,只需要按照一定的格式返回事件流,在客户端中,只需要为一些事件类型绑定监听函数,和处理其他普通的事件没多大区别。

HTTP 方法

Get 与 Post 的区别

  1. 数据传输方式不同:GET 请求通过 URL 传输数据,而 POST 的数据通过请求体传输。
  2. 安全性不同:POST 的数据因为在请求主体内,所以有一定的安全性保证,而 GET 的数据在 URL 中,通过历史记录,缓存很容易查到数据信息。
  3. 特性不同:GET 是安全(这里的安全是指只读特性,就是使用这个方法不会引起服务器状态变化)且幂等(幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同),而 POST 是非安全非幂等

PUT 和 POST 都是给服务器发送新增资源,有什么区别?

PUT 方法是幂等的:连续调用一次或者多次的效果相同(无副作用),而 POST 方法是非幂等的。

PUT 的 URI 指向是具体单一资源,而 POST 可以指向资源集合。

PUT 和 PATCH 都是给服务器发送修改资源,有什么区别?

PUT 和 PATCH 都是更新资源,而 PATCH 用来对已知资源进行局部更新。

直接覆盖资源的修改方式应该用 put,修改某一两个字段用 patch。

HTTP 是无状态的,所以用 cookie 和 session 来保持会话状态的。

服务器端创建 Session 之后,就可以调用 Session 相关的方法往 Session 中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有 SessionId。通过 Set-cookie

当客户端再次发送请求的时候,会将这个 cookie 带上,服务器接受到请求之后就会依据 cookie 中的 SessionId 找到相应的 Session,从而再次使用。正是这样一个过程,用户的状态也就得以保持了。

session, token, jwt token

jwt token

  1. header:声明类型 jwt 和加密算法,然后用 base64 加密。

    {
    'typ': 'JWT',
    'alg': 'HS256'
    }
    
  2. payload:声明令牌颁发者,过期时间,或者一些自定义信息,不要放敏感数据。然后用 base64 加密。

    {
        iss: jwt签发者
        sub: jwt所面向的用户
        aud: 接收jwt的一方
        exp: jwt的过期时间,这个过期时间必须要大于签发时间
        nbf: 定义在什么时间之前,该jwt都是不可用的.
        iat: jwt的签发时间
        jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
    }
    
  3. Signature 签名:base64 的 header 和 base64 的 payload,用 header 中声明的加密算法加密,密钥由服务端维护。

token 和 session

  1. session: 通常保存在服务器的内存中,用户多服务器开销大,而且分布式应用上需要配合 redis 存储管理 session 才能实现 session 共享。因为是基于 cookie 来进行用户识别的, cookie 如果被截获,用户就会很容易受到跨站请求伪造的攻击。
  2. token:不需要在服务端去保留用户的认证信息或者会话信息。服务器颁发 token,用户以后每次请求携带 token 就行,验证通过即可。token 会保存在服务端数据库或 redis 中。

token 和 jwt token

  1. 服务端验证 token 信息要进行数据的查询操作; 验证 JWT token 信息就不用, 在服务端使用密钥校验就可以,不用数据库的查询。
  2. jwt token 的有效期要设置的尽可能短。防止泄露后被盗用。
  3. jwt 的缺陷是一旦下发,服务端无法主动让 token 失效。解决办法是提供一个类似黑名单的机制,每次访问系统时先检查此 jwt 令牌是否已经被拉黑。但是此时又回到了使用 redis 或者数据库查询的路上了。
  4. token 好处是随时可以删除某个 token,阻断该 token 继续使用。

前端如何实现即时通讯?

  1. websocket 协议
    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。是一个全新的、独立的协议,基于 TCP 协议,与 http 协议兼容。浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
    常用类库:socket.io / ws
  2. 短轮询
    原理很简单,每隔一段时间客户端就发出一个请求,去获取服务器最新的数据,一定程度上模拟实现了即时通讯。
    优点:兼容性强,实现非常简单
    缺点:延迟性高,非常消耗请求资源,影响性能
  3. Ajax 的长轮询
    浏览器发出 XMLHttpRequest 请求,服务器端接收到请求后,会阻塞请求直到有数据或者超时才返回。
    浏览器 JS 在处理请求返回信息(超时或有效数据)后再次发出请求,重新建立连接。
    在此期间服务器端可能已经有新的数据到达,服务器会选择把数据保存,直到重新建立连接,浏览器会把所有数据一次性取回。
  4. service worker

Web Worker, Service Worker, Web Socket

web worker 的特点

状态码

2 开头 (请求成功)表示成功处理了请求的状态代码。

3 开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。

4 开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。

5 开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。

XSS,怎么防范

Cross-Site Scripting,跨站脚本注入。攻击者将脚本注入到目标网站进行攻击。XSS 的实质其实是 HTML 代码与 Javscript 代码的注入。

根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。

  1. 存储型,恶意代码被存储到了数据库中。危害最大,永久性的。

    • 攻击者将恶意代码提交到目标网站的数据库中。
    • 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
    • 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

    这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

  2. 反射型,恶意代码在 URL 中

    • 攻击者构造出特殊的 URL,其中包含恶意代码。
    • 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
    • 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

    反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。

  3. DOM 型,恶意代码也是在 URL 中

    • 攻击者构造出特殊的 URL,其中包含恶意代码。
    • 用户打开带有恶意代码的 URL。
    • 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

    DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

防范

  1. CSP
  2. 对于用户的任何输入要进行检查、过滤和转义
  3. 纯前端渲染
  4. 尽量不使用 innerHTML()等可以把数据作为 HTML 插入到页面的方法。

CSRF,怎么防范

跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。CSRF 攻击是攻击者借助受害者的 Cookie 骗取服务器的信任,可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

  1. 受害者登录 a.com,并保留了登录凭证(Cookie)
  2. 攻击者引诱受害者访问了b.com
  3. b.com 向 a.com 发送了一个请求:a.com/act=xx浏览器会默认携带a.com的 Cookie
  4. a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求
  5. a.com以受害者的名义执行了 act=xx
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作

CSRF 的两个特点:

防范:

  1. 服务器做同源检测,在 HTTP 头中有一个字段叫 Referer,记录了该 HTTP 请求的来源地址。
  2. Cookie 设置 HTTP-only。 Samesite。提交时要求附加本域才能获取到信息
  3. 请求中包含 token,而不是单单只用 cookie

SQL 注入

Sql 注入攻击,是通过将恶意的 Sql 查询或添加语句 插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击。

流程如下所示:

  1. 找出 SQL 漏洞的注入点
  2. 判断数据库的类型以及版本
  3. 猜解用户名和密码
  4. 利用工具查找 Web 后台管理入口
  5. 入侵和破坏

预防方式如下:

  1. 严格检查输入变量的类型和格式
  2. 过滤和转义特殊字符
  3. 对访问数据库的 Web 应用程序采用 Web 应用防火墙