计算机网络
计算机网络的七/五层模型
- 应用层:重要协议(HTTP,HTTPS,SSH,FTP,DNS)为应用软件而设的接口,设置软件之间的通信
- (表达层):处理通信系统间交换信息,包括数据格式变化、数据加密与解密、数据压缩与解压
URL 加密、图片解编码 - (会话层):负责在数据传输中设置和维护网络中两台计算机之间的通信连接,建立和管理会话
服务器验证用户登录,断点续传 - 传输层:端到端传输数据(TCP,UDP),流量控制,差错校验、数据包次序等传输问题
数据段 进程、端口 - 网络层:逻辑地址寻址(IP),实现不同网络之间的路径选择,分组传输,路由器的选择与转发
单位:分组;设备:路由器、三层交换机,防火墙 - 数据链路层:重要协议(ARP),IP 数据报封装成帧,硬件地址寻址,如何传输,差错校验,流量控制
单位:帧;设备:网卡、网桥、以太网(二层)交换机 - 物理层:物理接口通信通道上的原始比特流的传输
单位:比特;设备:中继器、集线器、网线
TCP 建立/断开连接
TCP 三次握手
- 第一次握手:建立连接时,客户端发送 SYN(syn=j)包到服务器,进入 SYN_SENT 状态,等待服务器确认
- 第二次握手:服务器收到 SYN 包,确认客户的 SYN(ack=j+1),自己也发送一个 SYN(syn=k)包,
即 SYN+ACK 包,服务器进入 SYN_RCVD 状态 - 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),客户端和服务器进入 ESTAB_LISHED 状态
为什么需要三次握手才能建立连接,两次不行吗?
确认服务器端和客户端的发送及接收能力正常,指定自己的初始化序列号为后面的可靠性传输做准备
1.相互确认:两次握手只能保证单向连接畅通
2.防止重复连接:(主要原因)为了防止旧的重复连接引起连接混乱问题
在网络状况比较复杂或网络状况比较差的情况下(丢包),发送方可能会连续发送多次建立连接的请求
如果 TCP 握手的次数只有两次,这个被客户端认为失效的消息到达了服务器端,对服务器端而言,以
为这是一个新的请求连接消息,就向客户端发送确认并建立连接。对客户而言,它认为没有给服务器
再次发送连接请求(因为上次的通话已经结束)所以客户忽略服务器的这个确认从而不发送数据,但
服务器则会一直等待客户的消息而处于忙等状态。这就导致了服务器资源被浪费
3 次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机 S 和 C 之间的通信,假定 C 给 S 发送一个连接请求分组,S 收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S 认为连接已经成功地建立了,可以开始发送数据分组。可是,C 在 S 的应答分组在传输中被丢失的情况下,将不知道 S 是否已准备好,不知道 S 建立什么样的序列号,C 甚至怀疑 S 是否收到自己的连接请求分组。在这种情况下,C 认为连接还未建立成功,将忽略 S 发来的任何数据分 组,只等待连接确认应答分组。而 S 在发出的分组超时后,重复发送同样的分组。这样就形成了死锁
第三次握手主要是为了防止已失效的请求报文段突然又传送到了服务端而产生连接的误判
TCP 四次挥手
- 第一次挥手:Client 发送一个 FIN,关闭 Client 到 Server 的数据传送,Client 进入 FIN_WAIT_1 状态
- 第二次挥手:Server 收到 FIN 后,发送一个 ACK 给 Client,确定序号为收到序号 +1(与 SYN 相同,一个
FIN 占用一个序号),Server 进入 CLOSE_WAIT 状态 - 第三次挥手:Server 发送一个 FIN,用来关闭 Server 到 Client 的数据传送,Server 进入 LAST_ACK 状态
- 第四次挥手:Client 收到 FIN 后,Client 进入 TIME_WAIT 状态,接着发送一个 ACK 给 Server,确定序号
为收到序号 +1, Server 进入 CLOSE 状态,完成四次挥手
为什么挥手比建立连接多一次?
连接建立过程中(握手),服务器端接收到建立连接的请求并回复 ACK 后,此时没有数据传输。所以在建立连接时第 2/3 步可合并。客户端发送完数据后请求断开连接,服务端可能还有数据需要发送,若同时回 ACK 和 FIN 报文段给客户端,可能造成数据的损坏或错误。所以服务器先发送 ACK 报文段,等服务端数据发送完再发送 FIN、ACK 报文段,就可以保证传输数据的完整性
当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了"。只有等到我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步握手
为什么需要四次挥手才能断开连接:
TCP 是全双工、点对点通信,发送方和接收方都需要 FIN 报文和 ACK 报文
为什么 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 连接
为什么客户端在第四次挥手后还会等待 2MSL?
MSL(Maximum Segment Lifetime 最长报文段寿命)报文在网络上存在的最长时间,超过这个时间报文将被丢弃保证第四次握手客户端发送的最后一个 ACK 报文段能够到达服务端。可能发生 ACK 报文丢失。如果服务端没接收到 ACK 报文的话,会重新发送 FIN 报文,只有当客户端等待了 2MSL 都没有收到重发的 FIN 报文时就表示服务端是正常收到了 ACK 报文,那么这个时候客户端就可以关闭了。防止“已失效的连接请求报文段”出现在本连接中。客户端在发送完最后一个 ACK 报文段后,再经过 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧连接请求报文段
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒钟发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接
TCP/UDP
TCP/UDP 区别
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
是否可靠 | 可靠传输(流量控制和拥塞控制) | 不可靠(尽最大努力交付) |
传输方式 | 面向字节流 | 面向报文 |
连接对象 | 一对一通信 | 一对一、一对多、多对一、多对多 |
首部开销 | 重量级(数据包 20 字节) | 轻量级(数据包 8 字节) |
适用场景 | 要求可靠传输的应用(文件传输) | 实时应用(IP 电话、视频会议、直播) |
TCP、UDP 可否同时监听同一端口
同一台机器的同一个端口只可以被一个进程使用,一个进程使用同一个端口同时监听 tcp、udp 请求是可以
端口的唯一性的标识不是端口号,而是端口号和协议名称的组合
TCP 如何保证传输可靠
- 数据分片:发送端对数据进行分片,接受端要对数据进行重组,由 TCP 确定分片的大小并控制分片和重组
- 到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认
- 超时重发:发送方在发送分片时设置超时定时器,在定时器超时之后没有收到相应的确认,重发分片数据
- 滑动窗口:TCP 连接每一方接受缓冲空间大小固定,接收端只允许另一端发送接收端缓冲区所能接纳数据
TCP 在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出 - 失序处理:作为 IP 数据报来传输 TCP 分片到达时可能失序,TCP 将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层
- 重复处理:作为 IP 数据报来传输的 TCP 分片会发生重复,TCP 的接收端必须丢弃重复的数据;
- 数据校验:TCP 将保持首部和数据的检验和(端到端),目的是检测数据在传输过程中的任何变化。如果收到分片的检验或有差错,TCP 将丢弃这个分片,并不确认收到此报文段导致对端超时并重发
TCP 流量控制
TCP 拥塞控制
哪些协议是基于 TCP,哪些协议是基于 UDP
TCP 支持的应用协议:Telnet(远程登录)、FTP(文件传输协议)、SMTP(简单邮件传输协议)
UDP 支持的应用协议:NFS(网络文件系统)、DNS(主域名称系统)、TFTP(通用文件传输协议)
HTTP/HTTPS
HTTP
HTTP 协议的发展历史
- HTTP/0.9
只有一个命令 GET
没有 HEADER 等描述数据的信息
服务器发送完毕,就关闭 TCP 连接 - HTTP/1.0
增加了很多命令
增加 status code 和 header
多字符集支持、多部分发送、权限、缓存等 - HTTP/1.1
持久连接
pipeline
增加 host 和其他一些命令 - HTTP 2
所有数据以二进制传输
同一个连接里面发送多个请求不再需要按照顺序来
头信息压缩以及推送等提高效率的功能
URI、URL
- URI,Uniform Resource Identifier/统一资源标志符
- URL,Uniform Resource Locator/统一资源定位器
URL 解析
http://localhost:8080/admin-index/article
- HTTP Protocol:http、https
- Host Name:localhost
- Port:8080
- Path:admin-index/article
HTTP 报文格式
请求消息 Request
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
- 请求行(request line)
- 请求头部(header)
- 空行
- 请求数据
响应消息 Response
# 状态行
HTTP/1.1 200 OK
# 消息报头
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
# 空行
# 响应正文
<html> ... </html>
菜鸟教程—HTTP:https://www.runoob.com/http/http-tutorial.html
HTTP 报文的请求头部
- Accept:浏览器可接受的 MIME 类型
Accept-Charset:浏览器可接受的字符集
Accept-Encoding:浏览器能够进行解码的数据编码方式
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到
Authorization:授权信息,通常出现在对服务器发送的 WWW-Authenticate 头的应答中。 - Connection:表示是否需要持久连接。如果 Servlet 看到这里的值为“Keep-Alive”,或者看到请求使用的是 HTTP 1.1(HTTP 1.1 默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如 Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet 需要在应答中发送一个 Content-Length 头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小 Content-Length:表示请求消息正文的长度
- Cookie:设置 cookie,这是最重要的请求头信息之一
- Host:初始 URL 中的主机和端口
- Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝
- Referer:包含一个 URL,用户从该 URL 代表的页面出发访问当前请求的页面
- User-Agent:浏览器类型,如果 Servlet 返回的内容与浏览器类型有关则该值非常有用
HTTP 状态码
- 1XX:指示信息,表示请求已接收,继续处理
100:Continue,表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应 - 2XX:成功,请求已被成功接收、理解、接收
200:OK,正常返回信息 - 3XX:重定向,要完成请求必须进行更进一步的操作
- 4XX:客户端错误,请求有语法错误或请求无法实现
400:bad request,客户端请求有语法错误,不能被服务器所理解
401:unauthorized,请求未经授权
403:forbidden,服务器收到请求,但拒绝提供服务
404:Not Found,请求资源不存在(输入错误的 URL) - 5XX:服务器端错误,服务器未能实现合法的请求
500:Internal Server Error,服务期发生不可预期的错误
502:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
503:Server unavailiable,临时的服务器维护或者过载,服务器当前无法处理请求
HTTP 长连接和短连接
HTTP 的长连接和短连接本质上是 TCP 长连接和短连接。HTTP 属于应用层协议,在传输层使用 TCP 协议,在网络层使用 IP 协议。 IP 协议主要解决网络路由和寻址问题,TCP 协议主要解决如何在 IP 层之上可靠地传递数据包,使得网络上接收端收到发送端所发出的所有包,并且顺序与发送顺序一致
HTTP 协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和上一次打开这个服务器上的网页之间没有任何联系。HTTP 是一个无状态的面向连接的协议,无状态不代表 HTTP 不能保持 TCP 连接,更不能代表 HTTP 使用的是 UDP 协议(无连接)
在 HTTP/1.0 中默认使用短连接:客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话
从 HTTP/1.1 起,默认使用长连接,用以保持连接特性:当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如 Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。使用长连接的 HTTP 协议,会在响应头加入:
Connection:keep-alive
一个 TCP 连接可以对应几个 HTTP 请求?
如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求
一个 TCP 连接中的 HTTP 请求发送可以一起发送吗(一起发三个请求,再三个响应一起接收)?
HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求
在 HTTP/1.1 可以完成多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的
在 HTTP/1.1 时代,浏览器是如何提高页面加载效率:
1.维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
2.和服务器建立多个 TCP 连接
浏览器对同一 Host 建立 TCP 连接的数量有没限制
Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别
HTTP 请求/响应报文组成
HTTP 响应报文组成:
状态码:服务器对请求的处理结果
响应头:描述服务器的基本信息,以及客户端如何处理数据
实体内容:服务器返回给客户端的数据
HTTP 响应报文组成:
状态码:服务器对请求的处理结果
响应头:描述服务器的基本信息,以及客户端如何处理数据
实体内容:服务器返回给客户端的数据
CORS 跨域请求的限制与解决
跨域行为是浏览器行为,一个跨域请求实际已经发送到服务端,服务端也返回了消息,然而浏览器在接收到返回信息的时候,发现该信息不是同源请求且没有允许跨域的限制,所以在解析消息的将该条消息屏蔽同时在控制台报错
CORS 跨域请求解决方法
- 利用浏览器允许标签的
跨域
这一特性,例如JOSNP
,但是JSONP
只能使用get
方法请求数据 - 'Access-Control-Allow-Origin':'*' //允许所有站点跨域请求,也可以设置成某一个具体站点
CORS 跨域限制
主要包括 methods content-type 和 请求头的限制
允许方法:默认允许方法 GET HEAD POST,其他的方法 PUT DELETE 默认是不允许的
允许 Content-Type
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
除了这三种,其他的 Content-Type 也需要使用预请求验证后,才能发送
其他限制
- 请求头限制,自定义的请求头默认是不允许的,也需要验证;官方文档,关于请求头的详细信息 https://fetch.spec.whatwg.org/#cors-safelisted-request-header
- XMLHttpRequestUpload 对象均没有注册任何事件监听器(很少用)
- 请求中没有使用 ReadableStream 对象(很少用)
CORS 预请求
在浏览器中输入 URL 后,执行的全部过程(HTTP 请求的过程)
- 判断是否需要跳转页面 Redirect
- 查看是否存在缓存
- DNS 域名解析:获取对应的 IP 地址
- 查询 DNS 缓存:浏览器缓存 --> 操作系统缓存 --> 操作系统的 hosts 文件
- 本地域名服务器(递归查询)
- TCP 三次握手建立连接
- 客户端发送 HTTP 请求的数据包
- 服务器接收到数据包,处理并返回请求响应的内容
- 浏览器解析 HTML 代码,并请求 HTML 代码中的资源
- TCP 断开(四次挥手)
- 浏览器渲染页面呈现给用户
Redirect
重定向可实现许多目标:
- 站点维护或停机期间的临时重定向
- 永久重定向将在更改站点的 URL,上传文件时的进度页等之后保留现有的链接/书签。
- 上传文件时的表示进度的页面
HTTP 协议的重定向响应的状态码为 3xx
CSP
Content-Security-Policy,内容安全策略
- 作用
限制资源获取
报告资源获取越权 - 限制方式
default-src 限制全局
制定资源类型:connect-src、img-src、style-src、manifest-src、font-src、media-src、frame-src、script-src
HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载
图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。如果发现用不了 HTTP2 呢?或者用不了 HTTPS,所以也就是只能使用 HTTP/1.1。那浏览器会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求
常用的端口及协议
TCP
- Telnet:终端模拟:23
- FTP:文件传输协议:20、21
- HTTP:超文本传输协议:80
- HTTPS:超文本传输安全协议:443
- SSH:远程连接服务:22
- TCP 服务端:8080
- Nginx 服务器:8888
- MySQL:默认端口是 3306
- Tomcat:默认端口是 8080
- ORACLE:默认端口 1521、1526
ping 命令是基于哪层协议
- 作用:ping 命令用来探测本机与网络中另一主机之间是否可达,如果两台主机之间 ping 不通,则表明这两台主机不能建立起连接
- 原理:ping 命令基于网络层的 ICMP 协议(Internet 控制报文协议)工作
ping 命令会发送一份 ICMP 回显请求报文给目标主机,并等待目标主机返回 CMP 回显应答报文。因为 ICMP 协议会要求目标主机在收到消息之后,必须返回 ICMP 应答消息给源主机,如果源主机在一定时间内收到了目标主机的应答,则表明两台主机之间网络是可达的
HTTP 中重定向和请求转发的区别
本质区别:转发是服务器行为,重定向是客户端行为
重定向:两次请求,浏览器地址发生变化,可以访问自己 web 之外的资源,传输的数据会丢失
请求转发:一次请求,浏览器地址不变,访问的是自己本身的 web 资源,传输的数据不会丢失
HTTP 如何保证安全传输
- 重要的数据,要加密:防止被抓包监听
- 非重要数据,要签名:防止内容被篡改
- 登录态怎么做:token
HTTP 如何传输大文件
-
数据压缩
浏览器在发送请求时都会带着 Accept-Encoding 头字段,里面是浏览器支持的压缩格式列表,例如 gzip、deflate、br 等,这样服务器就可以从中选择一种压缩算法,放进 Content-Encoding 响应头里,再把原数据压缩后发给浏览器。gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小。如在 Nginx 里就会使用 gzip on 指令,启用对 text/html 的压缩
-
分块传输
大文件整体不能变小,那就把它拆开,分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原。在 HTTP 协议里就是 chunked 分块传输编码,在响应报文里用头字段 Transfer-Encoding: chunked 来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送
https://www.cnblogs.com/traditional/p/15373999.html
缓存头 Cache-Control 的含义和使用
- 可缓存性
public
private
no-cache - 到期
max-age=<seconds>
s-maxage=<seconds>
max-stale=<seconds> - 重新验证
must-revalidate
proxy-revalidate - 其他
no-store
no-transform
缓存验证 Last-Modified 和 Etag 的使用
- Last-Modified
上次修改时间
配合 If-Modified-Since 或者 If-Unmodified-Since 使用
对比上次修改时间以验证资源是否需要更新 - Etag
数据签名
配合 lf-Match 或者 lf-Non-Match 使用
对比资源的签名判断是否使用缓存
HTTPS
HTTP 和 HTTPS 区别
HTTPS 相对于 HTTP 有哪些不同呢?其实就是在 HTTP 跟 TCP 中间加多了一层加密层 TLS/SSL
SSL(Secure Socket Layer,安全套接字层):保证进程和服务器间发送数据私密性、完整性、可鉴别性的协议
TLS(Transport Layer Security,传输层安全):SSL 的标准化,更为安全的升级版 SSL
申请证书 | 传输方式 | 连接端口 | |
---|---|---|---|
HTTP | 无需 | 明文传输 | 80 |
HTTPS | 申请证书,需要支付一定费用 | SSL+HTTP 协议构建的可进行加密传输 | 443 |
HTTPS 如何保证数据安全传输,连接建立的流程
Nginx 安装 SSL 配置 HTTPS 超详细完整全过程
HTTPS 采用混合加密机制,使用非对称密钥加密传输,对称密钥来保证密钥传输过程的安全,使用对称密钥加密进行通信
- 浏览器向服务器端发起 SSL 连接请求,将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以(公钥)证书的形式回发浏览器
- 浏览器验证证书合法性,使用伪随机数生成器生成通信加密所使用的对称密钥,再用证书公钥对对称秘钥进行加密,发送给服务器
- 服务器使用私钥解密,从而得到对称密钥,验证哈希,加密响应消息回发浏览器
- 浏览器解密响应消息,并对消息进行验证,之后进行加密进行数据传输
HTTPS 都使用哪些加密的算法(对称加密、非对称加密 )都怎么使用的?这些加密算法的理解
- 对称加密(Symmetric Key Algorithms)
- 特点:
- 加密方和解密方使用同一个密钥
- 加解密的速度比较快,适合数据比较长时使用
- 密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦
- 实现:
- DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合
- 3DES(Triple DES):是基于 DES,对一块数据用三个不同的密钥进行三次加密,强度更高
- AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高
- 特点:
- 非对称加密(Asymmetric Key Algorithms)
- 特点:
- 算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。把密钥分为公钥和私钥
- 实现:
- RSA:支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的
- DSA(Digital Signature Algorithm):数字签名算法
- ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学
- 特点:
对称加密算法加密数据 + 非对称加密算法交换密钥 + 数字证书验证身份 = 安全
HTTPS 加密算法用在哪个步骤?
SSL / TLS
HTTPS 加密流程
- 首先,客户端发起握手请求,以明文传输请求信息,包含版本信息,加密-套件候选列表,压缩算法候选列表,随机数,扩展字段等信息(
这个没什么好说的,就是用户在浏览器里输入一个HTTPS网址,然后连接到服务端的443端口。
) - 服务端的配置,采用 HTTPS 协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。
这套证书其实就是一对公钥和私钥。
如果对公钥不太理解,可以想象成一把钥匙和一个锁头,只是世界上只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。 - 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 以及证书。(
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
) - 客户端验证证书的合法性,包括可信性,是否吊销,过期时间和域名。(
这部分工作是由客户端的SSL/TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警示框,提示证书存在的问题。如果证书没有问题,那么就生成一个随机值。然后用证书(也就是公钥)对这个随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
) - 客户端使用公匙对对称密匙加密,发送给服务端。(
这部分传送的是用证书加密后的随机值,目的是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
) - 服务器用私钥解密,拿到对称加密的密匙。(
服务端用私钥解密后,得到了客户端传过来的随机值,然后把内容通过该随机值进行对称加密,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
) - 传输加密后的信息,这部分信息就是服务端用私钥加密后的信息,可以在客户端用随机值解密还原。
- 客户端解密信息,客户端用之前生产的私钥解密服务端传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策
Get/Post
HTTP 中与服务器交互方法
对资源的增,删,改,查操作,其实都可以通过 GET/POST 完成,不需要用到 PUT 和 DELETE
作用 | HTTP 报文信息存放位置 | 幂等 | 说明 | 数据大小限制 | |
---|---|---|---|---|---|
Get | 查 | URL | 幂等 | 会被浏览器主动缓存;?分割 URL 和参数,参数之间以&相连(限制:整个 URL 长度) | 一般不超过 2KB |
Post | 改 | 报文体 | 非幂等 | 不可缓存 | 理论上没有限制 |
Put | 增 | 非幂等 | 向指定资源位置上传其最新内容 | ||
Delete | 删 | 幂等 | 请求服务器删除 Request-URI 所标识的资源 |
安全:该操作用于获取信息而非修改信息。仅是获取资源信息,像数据库查询,不修改数据,不影响资源状态
幂等:对同一 URL 的多个请求应该返回同样的结果
Get/Post 区别
传送方式 | 传送长度 | 产生数据包 | 安全性 | 使用 | |
---|---|---|---|---|---|
Get | 地址栏传输 | 有长度限制 | 1 个:HTTP Header 和 Data 一并发送,服务器响应 200 | 较弱 | 数据查询 |
Post | 报文传输 | 无长度限制 | 2 个:先发送 HTTP Header,服务器响应 100-Continue,浏览器再发送 Data,服务器响应 200 | 较强 | 数据增删改 |
多次 Post 怎么保证数据安全
如果不小心提交了两次重复的数据,要怎么解决
操作:重复点击或者网络重发
- 点击提交按钮两次
- 使用浏览器后退按钮重复之前的操作,导致重复提交表单
- Nginx 重发等情况
解决:
-
使用 Post/Redirect/Get 模式
Post-Redirect-Get (PRG)模式:在提交后执行页面重定向。能避免用户按 F5 导致的重复提交,而其也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退按导致的同样问题
-
在 session 中存放一个特殊标志
在服务器端,生成一个唯一的标识符,将它存入 session,同时将它写入表单的隐藏字段中,然后将表单页面发给浏览器,用户录入信息后点击提交,在服务器端,获取表单中隐藏字段的值,与 session 中的唯一标识符比较,相等说明是首次提交,就处理本次请求,然后将 session 中的唯一标识符移除;不相等说明是重复提交,就不再处理
-
乐观锁
insert 使用唯一索引 update 使用 乐观锁 version 版本法
POST 有哪几种编码
application/x-www-form-urlencoded
multipart/form-data
application/json
text/xml
Post 发送 JSON,请求头需要加什么?
Content-Type: application/json
RESTful 的理解
RESTful(Representational State Transfer,表现层状态转化)架构,目前最流行的一种互联网软件架构。结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
-
资源(Resources)
"表现层"其实指的是"资源"(Resources)的"表现层"。所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI。要获取这个资源,访问它的 URI 就可以,因此 URI 就成了每一个资源的地址或独一无二的识别符。所谓"上网",就是与互联网上一系列的"资源"互动,调用它的 URI
-
表现层(Representation)
"资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式;图片可以用 JPG 格式表现,也可以用 PNG 格式表现。URI 只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而 URI 应该只代表"资源"的位置。它的具体表现形式,应该在 HTTP 请求的头信息中用 Accept 和 Content-Type 字段指定,这两个字段才是对"表现层"的描述
-
状态转化(State Transfer)
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。互联网通信协议 HTTP 协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是 HTTP 协议。具体来说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源(也可以用于更新资源),PUT 用来更新资源,DELETE 用来删除资源。
RESTful 架构:
- 每一个 URI 代表一种资源
- 客户端和服务器之间,传递这种资源的某种表现层
- 客户端通过四个 HTTP 动词,对服务器端资源进行操作,实现"表现层状态转化"
设计误区:
-
URI 包含动词
- 因为"资源"表示一种实体,所以应该是名词,URI 不应该有动词,动词应该放在 HTTP 协议中
- 某个 URI 是/posts/show/1,其中 show 是动词,这个 URI 就设计错了,正确的写法应该是/posts/1,然后用 GET 方法表示 show
- 如果某些动作是 HTTP 动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户 1 向账户 2 汇款 500 元,错误的 URI 是:POST /accounts/1/transfer/500/to/2。正确的写法是把动词 transfer 改成名词 transaction,资源不能是动词,但是可以是一种服务
POST /transaction HTTP/1.1 Host: 127.0.0.1 from=1&to=2&amount=500.00
-
URI 中加入版本号
因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个 URI。版本号可以在 HTTP 请求头信息的 Accept 字段中进行区分
http://www.example.com/app/1.0/foo --> Accept: vnd.example-com.foo+json; version=1.0 http://www.example.com/app/1.1/foo --> Accept: vnd.example-com.foo+json; version=1.1
Cookie/Session
HTTP 是无状态协议,如何保存用户状态?用户登录信息可以有哪些方式保存
HTTP 不保存状态,即⽆状态(stateless)协议。HTTP 协议⾃身不对请求和响应之间的通信状态进⾏保存
- Cookie:一小段文本信息。通过检查客户身上的“通行证”来确定客户身份的话。客户端请求服务器,如果服务器需要记录该用户状态,就使用 Response 向客户端浏览器发送一个 Cookie。客户端浏览器会把 Cookie 保存。当浏览器再请求该网站时,浏览器把请求的网址连同该 Cookie 一同提交给服务器。服务器检查该 Cookie,以此来辨认用户状态。服务器还可以根据需要修改 Cookie 的内容
- Session:记录客户状态的机制,通过检查服务器上的“客户明细表”来确认客户身份。不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。服务器把客户端信息以某种形式记录在服务器上。如果客户端请求里不包含有 SessionID,则为客户端创建一个 Session 并生成一个与此 Session 相关的 SessionID。客户端浏览器再次访问时,服务器按照这个 SessionID 把 Session 从服务器内存中查出
Cookie 和 Session 的工作原理
Cookie:
- 浏览器端第一次发送请求到服务器端
- 服务器端创建 Cookie,该 Cookie 中包含用户的信息,服务器会通过响应携带 Cookie,在产生响应时会产生 Set-Cookie 响应头,然后将该 Cookie 发送到浏览器端,max-age 和 expires 设置过期时间
- 当浏览器再次向服务器发送请求时,会产生 Cookie 请求头,将之前服务器的 Cookie 信息再发送给服务器,下次请求会自动带上
- 服务器端通过 Cookie 中携带的数据跟踪用户状态
Session:
- 浏览器端第一次发送请求到服务器端
- 服务器端创建一个 Session,同时会创建一个特殊的 Cookie(name 为 JSESSIONID 的固定值,value 为 session 对象的 ID),然后将该 Cookie 发送至浏览器端
- 浏览器端再次访问服务器端时就会携带该 name 为 JSESSIONID 的 Cookie 对象
- 服务器端根据 name 为 JSESSIONID 的 Cookie 的 value(sessionId),在服务器内查找 Session 对象,从而跟踪到用户状态
Cookie 与 Session 的区别
- 存储方式:Cookie 是 String 类型;Session 是 Object 类型
- 存储位置:Cookie 存放在客户端浏览器;Session 存放在服务器
- 安全性:Cookie 明文存放在客户端,易泄露,安全性弱; Session 存在服务器,对客户端透明,安全性强
- 有效期:
Cookie 保存在硬盘,只需设置 MaxAge 属性值为比较大的正整数,即使关闭浏览器,Cookie 还是存在的
Session 保存在服务器,设置 MaxInactiveInterval 属性值{Session 的生命周期是间隔变化的,比如每访问一次就重新记时,若整个间隔时间内没有访问则失效}来确定 Session 的有效期。并且 Session 依赖于名为 JSESSIONID 的 Cookie,该 Cookie 默认的 MaxAge 属性为-1(表示仅当前浏览器内有效,并且各浏览器窗口间不共享),如果关闭了浏览器,该 Session 虽然没有从服务器中消亡,但是会失效 - 对服务器的负担:
Cookie:保存在客户端上,不占用服务器资源
Session:保存在服务器上,用户都会产生一个 Sessioon,如果并发访问的用户非常多,会消耗大量内存
Session 和 Cookie 应该如何去选择
- 数据复杂性:首选 Session。Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据
- 安全性:首选 Session。Cookie 存在浏览器,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,
可以将 Cookie 值进行加密,然后在服务器进行解密 - 大型网站,不建议将所有用户信息都存储到 Session 中。用户所有信息都存在 Session 中,开销是非常大
登录信息放在 Session 还是 Cookie 中?
- Session 保存在服务器中,更加安全。但如果在高并发情况下,用户群体多的话,服务器压力很大(适合用户群体少的后台管理系统)
- Cookie 保存在浏览器端,京东、淘宝等大型网站都将用户信息保存在 Cookie 中。虽然不安全,但是我们可以对信息加密或者将涉及隐私的信息不保存到 Cookie,不存在服务器压力
Cookie,sessionStorage 和 localStorage 的区别
-
同:都存储在客户端
-
异:
- 存储大小:
Cookie 数据大小不能超过 4K
sessionStorage 和 localStorage 也有存储大小的限制,但比 Cookie 大得多,可以达到 5M 或更大 - 有效时间:
localStorage:存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
sessionStorage:数据在当前浏览器窗口关闭后自动删除
Cookie:设置的 Cookie 过期时间之前一直有效,即使窗口或浏览器关闭 - 数据与服务器之间的交互方式:
cookie 的数据会自动的传递到服务器,服务器端也可以写 cookie 到客户端
sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
- 存储大小:
SYN 攻击
服务器端的资源分配是在第 3 次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到 SYN 洪泛攻击
SYN 攻击原理:Client 在短时间内伪造大量不存在的 IP 地址,并向 Server 不断地发送 SYN 包,Server 则回复确认包,并等待 Client 确认,由于源地址不存在,因此 Server 需要不断重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,导致正常的 SYN 请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DDoS 攻击
防御 SYN 攻击的方法:
- 超时(SYN Timeout)时间
- 增加最大半连接数
- 过滤网关防护
- SYN Cookies 技术:用一个 Cookie 来响应 TCP SYN 请求的 TCP 实现。当 Server 接收到一个 Client 的 SYN 数据包时,Server 通过特定的算法把 半开连接信息 编码成“Cookie”,随 SYN-ACK 包一同发给 Client,这样在连接完全建立前 B 不保存任何信息。 缺点:最明显的就是 B 不保存连接的半开状态,就丧失了重发 SYN-ACK 消息的能力,这一方面会降低正常用户的连接成功率
文件上传漏洞是如何发生的?如何防范?
文件上传漏洞指的是用户上传一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力
防范文件上传漏洞:
- 文件上传的目录设置为不可执行
- 判断文件类型:在判断文件类型的时候,可以结合使用 MIME Type,后缀检查等方式。因为对于上传文件,不能简单地通过后缀名称来判断文件的类型,因为攻击者可以将可执行文件的后缀名称改为图片或其他后缀类型,诱导用户执行
- 对上传的文件类型进行白名单校验,只允许上传可靠类型
- 限制上传文件的大小
- 单独设置文件服务器的域名
JavaWeb
Servlet 的生命周期
- Servlet 初始化:init()
- Servlet 处理请求:service(),根据请求的不同调用不同的 doGet()/doPost()方法
- Servlet 销毁:destroy()
- Servlet 由 JVM 的垃圾回收器进行垃圾回收
Servlet API 中 forward() 与 redirect()的区别?
- forward():仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址
- redirect():完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用 forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用 sendRedirect()
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于