目前,由国际化标准组织ISO制定的网络体系结构国际标准是 OSI七层模型。OSI的七层协议体系结构的概念清楚,理论也比较完整,但它既复杂又不实用。TCP/IP体系结构则不同,但它却得到了非常广泛的应用。TCP/IP是一个四层的体系结构,它包含应用层、运输层、网际层和网络接口层(用网际层这个名字是强调这一层是为了解决不同网络的互联问题)。不过从实质上讲,TCP/IP只有最上面的三层,因为最下面的网络接口层并没有什么具体内容。因此在学习计算机网络的原理时往往采取折中的办法,即综合OSI和TCP/IP的优点,采取一种只有五层协议的体系结构,这样既简洁又能将概念阐述清楚。有时为了方便,也可把最底下两层称为网络接口层。
五层协议的体系结构知识为了介绍网络原理而设计的,实际应用还是采用TCP/IP四层体系结构。
五层的体系结构至上往下,最终可以实现端对端之间的数据传输与通信,他们各自负责一些什么,最终如何实现端对端之间的通信?
所以通过上面五层的各司其职,实现物理传输介质–MAC地址–IP地址–端口号–获取到数据根据应用层协议解析数据最终实现了网络通信和数据传输。
客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西。其中比较重要的字段有:
(1)序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认号(acknowledgement number):Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
(3)标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:
需要注意的是:不要将确认序号Ack与标志位中的ACK搞混了。确认方Ack=发起方Seq+1,两端配对。
为什么建立连接需要三次握手?
握手两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论的。第三次握手是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误
假设一下如果没有第三次握手,而是两次握手后我们就认为连接建立,那么会发生什么?具体情况就是:C端发出去的第一个网络连接请求由于某些原因在网络节点中滞留了,导致延迟,直到连接释放的某个时间点才到达S端,这是一个早已失效的报文,但是此时S端仍然认为这是C端的建立连接请求第一次握手,于是S端回应了C端,第二次握手。如果只有两次握手,那么到这里,连接就建立了,但是此时C端并没有任何数据要发送,而S端就会傻傻的等待着,造成很大的资源浪费。所以需要第三次握手,只有C端再次回应一下,就可以避免这种情况。
为什么比建立连接时多了一次握手?
可以看到这里服务端的ACK(回复客户端)和FIN(终止)消息并不是同时发出的,而是先ACK,然后再FIN,这也很好理解,当客户端要求断开连接时,此时服务端可能还有未发送完的数据,所以先ACK,然后等数据发送完再FIN。这样就变成了四次握手了。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
TCP如何保证长连接
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
HTTP是一种应用层的超文本传输协议,这就意味着它能够传输包括文字、图片、音频、视频等格式的内容。HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
HTTP是一种应用层协议,它通过tcp实现了可靠的数据传输。详细的交互流程如下:
HTTP是无状态的,同一个客户端对服务端多次请求,服务端无法识别是否是同一个用户。但是随着交互式Web应用的兴起,像在线购物网站,需要登录的网站等等,马上就面临一个问题,那就是要管理会话,必须记住哪些人登录系统, 哪些人往自己的购物车中放商品, 也就是说我必须把每个人区分开,这就是一个不小的挑战,因为HTTP请求是无状态的,因此引入了Cookie、Session和Token的技术。
为了在去状态的HTTP请求中区别不同的用户,于是有人就想出了一个办法,这个办法就是给服务端存着每个客户端的唯一会话标识sessionId(一个随机的字符串),然后下发给客户端,保存在客户端的的cookie中。每次客户端向服务端发起HTTP请求的时候,就会把cookie中的随机字符串(sessionId)一并捎过来,这样就能区分开是哪个用户发起的请求了。(由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,自身安全性较差,我们应该在服务器的的session里保存私密的信息以及超过4096字节的文本)
这样,服务器就增加了压力,因为服务器需要保存所有用户的sessionId。如果有上千上万个sessionId,对服务器来说就是一个巨大的开销,严重地限制了服务器的扩展能力。比如说用两个机器组成了一个集群,小明通过机器A登陆了系统,那sessionId就会保存在机器A上,假设小明的下一次请求被转发到机器B怎么办?机器B可没有小F的sessionId啊。有时候会采用session sticky的小技巧,就是让小明的请求一直粘连在机器A上。但是这也不管用,要是机器A挂掉了,还得转到机器B上去。
为了解决A机器挂掉的问题,只好做sessionId的复制了,把sessionId在两个机器之间搬来搬去。
后来有个叫Memcached的支了招: 把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session 的机器挂了, 所有人都得重新登录一遍, 估计得被人骂死。
也尝试把这个单点的机器也搞出集群,增加可靠性。但不管如何,这小小的session对服务器来说都是一个沉重的负担。
于是,就有人提出了摆脱session的想法。具体就是不再在服务端保存sessionId了,让客户端去保存一个服务端生成的token,每次请求的时候附加上这个token,服务端只要对这个token进行相应的校验就可以完成身份验证。比如说,小明已经登陆了系统,服务端给他返回了一个令牌(token),里面包含了小明的userId,下一次小明再通过HTTP请求访问服务端的时候,就把这个token通过HTTP的Header带过来就可以了。
因为服务端不再存sessionId了,也不会存token,那么就可能会造成有心怀不轨的人伪造token来做坏事。因此,服务端需要对token做一些防伪造的操作,具体是对数据做一个签名。比如说用HMAC-SHA256算法加上一个只有服务器知道的密钥,对数据做一个签名,然后把签名和数据一起作为token,由于密钥别人不知道,就无法伪造token了。服务器并不会保存这个token,当小明再次将token发到服务器的时候,服务端会用同样的HMAC-SHA256算法和同样的密钥去对数据再计算一次签名,并和token中的签名做一个比较,如果相同的话,就可以判断出小明已经登陆过,并且可以直接取到小明的userId;如果不相同,则数据部分肯定被人篡改过,这时就能够做一些身份校验失败的相应处理。
这样一来,服务器就不需要保存sessionId了,只需要生成token,然后校验token,相当于用CPU计算时间换回了存储空间。解决了sessionId这个负担,可以说是无事一身轻。机器集群现在可以轻松地做水平扩展,用户访问量增大的时候直接加机器就OK。
总结
方法类型 | 描述 |
---|---|
GET | 请求指定的页面信息,并返回实体主体。 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 |
OPTIONS | 允许客户端查看服务器的性能,可以查询针对请求URI指定资源支持的方法 |
HEAD | 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
DELETE | 请求服务器删除指定的页面。 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
禁用部分不安全的HTTP方法
众所周知,GET、POST是最为常见方法,而且大部分主流网站只支持这两种方法,因为它们已能满足功能需求。其中,GET方法主要用来获取服务器上的资源,而POST方法是用来向服务器特定URL的资源提交数据。而其它方法出于安全考虑被禁用,所以在实际应用中,九成以上的服务器都不会响应其它方法,并抛出404或405错误提示。以下列举几个HTTP方法的不安全性:
除GET、POST之外的其它HTTP方法,其刚性应用场景较少,且禁止它们的方法简单,即实施成本低。一旦让低权限用户可以访问这些方法,他们就能够以此向服务器实施有效攻击,即威胁影响大。
Header类型 | 解释 | 示例 |
---|---|---|
Accept | 指定客户端能够接收的内容类型 | Accept: text/plain, text/html |
Accept-Charset | 浏览器可以接受的字符编码集 | Accept-Charset: iso-8859-5 |
Accept-Encoding | 指定浏览器可以支持的web服务器返回内容压缩编码类型 | Accept-Encoding: compress, gzip |
Accept-Language | 浏览器可接受的语言 | Accept-Language: en,zh |
Accept-Ranges | 可以请求网页实体的一个或者多个子范围字段 | Accept-Ranges: bytes |
Authorization | HTTP授权的授权证书 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control: no-cache |
Connection | 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) | Connection: close |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 | Cookie: $Version=1; Skin=new; |
Content-Length | 请求的内容长度 | Content-Length: 348 |
Content-Type | 请求的与实体对应的MIME信息 | Content-Type: application/x-www-form-urlencoded |
Date | 请求发送的日期和时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
Expect | 请求的特定的服务器行为 | Expect: 100-continue |
From | 发出请求的用户的Email | From: [email protected] |
Host | 指定请求的服务器的域名和端口号 | Host: www.zcmhi.com |
If-Match | 只有请求内容与实体相匹配才有效 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since | 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 | If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
If-None-Match | 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range | 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag | If-Range:“737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since | 只在实体在指定时间之后未被修改才请求成功 | If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
Max-Forwards | 限制信息通过代理和网关传送的时间 | Max-Forwards: 10 |
Pragma | 用来包含实现特定的指令 | Pragma: no-cache |
Proxy-Authorization | 连接到代理的授权证书 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 只请求实体的一部分,指定范围 | Range: bytes=500-999 |
Referer | 先前网页的地址,当前请求网页紧随其后,即来路 | Referer: http://www.zcmhi.com/archives/71.html |
TE | 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 | TE: trailers,deflate;q=0.5 |
Upgrade | 向服务器指定某种传输协议以便服务器进行转换(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent | User-Agent的内容包含发出请求的用户信息 | User-Agent: Mozilla/5.0 (Linux; X11) |
Via | 通知中间网关或代理服务器地址,通信协议 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 关于消息实体的警告信息 | Warn: 199 Miscellaneous warning |
值 | 状态 | 说明 |
---|---|---|
200 | OK | 表示请求被服务器正常处理 |
204 | No Content | 表示请求已成功处理,但是没有内容返回,也就是返回的响应报文中没有报文实体,浏览器页面不会发生更新 |
301 | Moved Permanently | 永久重定向,表示请求的资源已经永久的搬到了其他位置,就是说资源已经被分配了新的URI |
302 | Found | 临时重定向,表示请求的资源临时搬到了其他位置请求的资源暂时被配到到了新的URI |
400 | Bad Request | 表示请求报文存在语法错误或参数错误,服务器不理解服务器不应该重复提交这个请求。 |
401 | Unauthorized | 表示发送的请求需要有HTTP认证信息或者是认证失败了返回401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部以质询用户信息 |
403 | Forbidden | 表示对请求资源的访问被服务器拒绝了 |
404 | Not Found | 表示服务器找不到你请求的资源 |
500 | Internal Server Error | 表示服务器执行请求的时候出错了,可能是Web应用有bug或临时故障 |
503 | Service Unavailable | 表示服务器超负载或正停机维护,无法处理请求 |
HTTP报文的分类有两种:请求报文和响应报文。顾名思义,请求报文就是客户端向服务端发送请求的信号,响应报文就是服务端响应处理后回传给客户端的信号。
HTTP 请求报文由四部分组成,分别是请求行、请求头、空行和请求体,其中空行也是组成部分之一,作用是进行分隔,必不可少。
客户端向服务端发送请求之后,服务器接收并处理客户端发过来的请求后正常情况下会返回一个HTTP的响应消息,这个就是响应报文。
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。形式上除了状态行之外,其他三个部分与请求报文类似。
Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。这里我们只讨论 HTTP 缓存相关内容。浏览器缓存主要是 HTTP 协议定义的缓存机制。HTML meta 标签,例如
含义是让浏览器不缓存当前页面。但是代理服务器不解析 HTML 内容,一般应用广泛的是用 HTTP 头信息控制缓存。
大致分为两种:强制缓存和对比缓存。强制缓存如果命中缓存不需要和服务器端发生交互,而对比缓存不管是否命中都要和服务器端发生交互。强制缓存的优先级高于对比缓存。不管是哪种缓存,在第一次请求的的逻辑都是一致的,此时缓存数据库中没有对应的缓存数据,需要请求服务器,服务器返回后,将数据根据头信息规则存储至缓存数据库中,如下图:
可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control 来表明规则。
Expires
Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。有一个问题是由于使用具体时间,如果时间表示出错或者没有转换到正确的时区(服务器和客户端时区不同)都可能造成缓存生命周期出错。并且 Expires 是 HTTP/1.0 的标准,现在更倾向于用 HTTP/1.1 中定义的 Cache-Control。两个同时存在时也时,Cache-Control 的优先级比Expires高。
Cache-Control
Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。
假设浏览器存在一个缓存数据库,用于存储缓存信息。在第二次请求的时候,已存在缓存数据时,仅基于强制缓存,请求数据的流程如下:
我们可以看到,如果强制缓存生效,不需要再和服务器发生交互,直接从缓存数据库读取数据。
缓存的资源到期了,并不意味着资源内容发生了改变,如果和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源。
对比缓存有两种组合,分别为Last-modified/If-Modified-Since和Etag/If-None-Match,如果两种组合同时存在,Etag/If-None-Match优先级比Last-modified/If-Modified-Since高。
Last-modified/If-Modified-Since
Last-modified: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since 即为之前记录下的时间。服务器端收到带 If-Modified-Since 的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200,若没有修改过则返回 304。
注意:如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。
Etag/If-None-Match
由服务器端上生成的一段 hash 字符串,第一次请求时响应头带上 ETag: abcd,之后的请求中带上 If-None-Match: abcd,服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对,不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
忽略第一次请求,在第二次有缓存的情况下,HTTP缓存的策略流程如下:
HTTP协议因为其轻、小、快、简单,所以在全世界普及开来,各种应用都离不开它。但是随着业务复杂度的提高,HTTP的这些优点逐渐成为了短板。所以就开始各种打补丁,比如为了管理状态而诞生的Cookie,为了安全而诞生的超级补丁SSL(HTTPS)等等。
1、容易被窃听
HTTP使用明文进行传输,因此传输内容可能会被窃听。以太网工作方式是将要发送的数据包发往连接在一起的所有主机。在包头中包括所有应该接收数据包的主机的正确地址,因为只有与数据包中目标地址一致的那台主机才能接收到信息包,但是当主机工作在监听模式下的话不管数据包中的目标物理地址是什么,主机都将可以接收到。
2、容易被伪装
HTTP协议中不管是请求还是响应都不会对客户端和服务器的身份进行确认。在HTTP协议通信时,任何人都可以发起请求,服务器只要接收到请求,不管对方是谁都会返回一个响应(当然,可以在服务端对IP或者端口进行限制)。因此,可能服务器或者客户端并不是我们想象中的对方。而且,对于无意义的请求服务器也会照单全收,可能会遭遇DoS攻击。
3、容易被篡改
对于信息的准确性我们可以用一个专业术语—报文完整性来说明,由于HTTP无法验证通信报文的完整性,因此,在请求或者响应发送之后到接收这段时间内,传输的内容可能已经被篡改(中间人攻击)。
HTTPS端口号:443
为了解决这些问题,HTTPS顺应而生。可以这么理解,HTTPS是安全版的HTTP,它不是一个新的协议,而是HTTP 加上加密处理(解决HTTP通信使用明文被窃听问题)和认证(解决HTTP不验证通信方的身份被伪装问题)以及完整性保护(解决HTTP无法证明报文完整性被篡改问题)后的东西。
HTTPS是 HTTP通信接口部分用SSL(Secure Socket Layer)和 TLS(Transport Layer Security)协议代替而已。通常,HTTP 直接和 TCP 通信。当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 通信了。简言之,所谓 HTTPS,其实就是身披SSL 协议这层外壳的 HTTP。
近代的加密方法中加密算法是公开的,而密钥却是保密的。就比如:制造一把锁的方法是公开的,但是要想解开这把锁得有钥匙(别说可以砸,这触及到我的知识盲区了),这个钥匙就相当于密钥。你虽然知道是什么加密算法,但你没密钥就是没法还原密文。通过这种方式得以保持加密方法的安全性。现在的加密方法一般有两种:对称密钥加密和非对称密钥加密。
存在的问题:如何把密钥安全的发给对方?(如果不发密钥,对方解不了密。发送就有安全风险,而且密钥如果能安全发送,那数据也可以,那还要密钥干啥?所以就很矛盾)另外还要安全的保管接受到的密钥。
解释一下这幅图: Alice是发送方,Bob是接收方。Alice(发送方)使用Bob(接收方)的公钥对要发送的明文数据进行加密,通过网络传输给Bob,Bob接收到密文后使用自己的私钥解密得到明文。那有人会有疑问了?密文和公钥都在网络上传输,肯定也有被监听的风险啊。对,没错,不过根据密文和公钥想还原出明文是非常非常非常非常非常非常困难的。
对称加密因为加解密使用的是同一密钥,相对非对称加解密使用不同密钥,对称加密对CPU资源的消耗会更少,速度会更快,更适合大量数据的加密。但是对称加密需要将密钥发送给通信的另一方,如果密钥在传输过程中被截获,那就白忙活了。所以这时候就需要非对称加密发挥优势了,非对称加密可以用来传输对称加密的密钥。
HTTPS当然使用复杂的混合加密机制(对称加密和非对称加密一起使用)。其实对称加密已经够用,只是有一个问题,对称加密的密钥如何发送给通信的另一方。我们把信息装进一个带锁的箱子了,并把箱子发送给另一方,对方如何打开箱子才是问题的关键。这一过程也叫做密钥交换。混合加密机制就是在密钥交换阶段使用非对称加密方式,之后使用对称加密方式进行传输。
非对称密钥加密方式也存在一些问题,就是无法证明公开密钥就是接收方公开的那个密钥,而不是被攻击者调包的密钥。为了解决这个问题,可以使用由数字证书认证机构(CA,Certificate Authority)和其相关机构颁发的公开密钥证书。数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上。这货就相当于是公证处,大家都相信公证处。以下是数字证书认证机构的业务流程:
1、服务器的运营人员向数字证书认证机构提出公钥申请。
2、认证机构在判明申请者的身份之后,对已申请的公钥做数字签名(非对称加密使用私钥进行加密叫数字签名)。
3、认证机构分配这个已签名的公钥,并将该公钥放入公钥证书后绑定在一起。
4、服务器将证书发送给客户端,客户端使用认证机构的公钥解开证书,进行验证。
前置知识已经讲完了。我们回到刚才说要讲的SSL协议上来,HTTPS使用SSL和TLS这两个协议进行安全通信。TLS是以SSL为原型开发的协议,有时会统一称该协议为SSL。看下HTTPS的通信过程:
这个图有12个步骤,别慌,我先用通俗的话讲一下流程,后面再给出具体的每一步干什么。
通俗版:
客户端向一个需要HTTPS访问的网站发起请求,服务器将证书(包含公钥,非对称加密发送)发给客户端进行校验,客户端校验成功后,会给服务器发送一个使用公钥加密后的随机串,服务器使用私钥解密这个串,从此服务器使用这个随机串进行对称加密开始和客户端进行通信,客户端拿到消息使用随机串进行解密。
专业版:
在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。