关于浏览器的乱七八糟的那些知识
信息
最近在各种面试,也总结了一些关于浏览器和网络协议之类的知识。可以作为一个大纲,如果想深入研究的话请各自翻阅更加详细的资料。
OSI 七层与 TCP/IP 五层模型
- OSI 七层模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
- TCP/IP 五层模型
- 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
- 传输层:TCP,UDP
- 网络层:IP,ICMP,RIP,OSPF,BGP,IGMP
- 数据链路层:SLIP,CSLIP,PPP,ARP,RARP,MTU
- 物理层
应用层的协议哪些是基于 TCP 协议的,哪些是基于 UDP 协议的
基于 TCP 协议的
- FTP(文件传输协议):定义了文件传输协议,使用 21 端口。
- TELNET(远程登陆协议):一种用于远程登陆的端口,使用 23 端口,用户可以以自己的身份远程连接到计算机上,可提供基于 DOS 模式下的通信服务。
- SMTP(简单邮件传输协议):邮件传送协议,用于发送邮件。服务器开放的是 25 号端口。
- POP3(邮件读取协议):它是和 SMTP 对应,- POP3 用于接收邮件。POP3 协议所用的是 110 端口。
- HTTP(超文本传输协议):是从 Web 服务器传输超文本到本地浏览器的传送协议。
- HTTPS(超文本传输安全协议)
基于 UDP 协议的
- TFTP(简单文件传输协议):该协议在熟知端口 69 上使用 UDP 服务。
- SNMP(简单网络管理协议):使用 161 号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
- BOOTP(引导程序协议,DHCP 的前身):应用于无盘设备
- DHCP(动态主机配置协议):是一个局域网的网络协议
- RIP(路由信息协议):基于距离矢量算法的路由协议,利用跳数来作为计量标准。
- IGMP(Internet 组管理协议)
基于 TCP 和 UDP 协议的
- DNS(域名系统):DNS 区域传输的时候使用 TCP 协议。域名解析时使用 UDP 协议。DNS 用的是 53 号端口。
- ECHO(回绕协议)
HTTP 状态码
- 1XX 信息性状态码
- 100 继续
- 101 切换协议
- 2XX 成功状态码
- 200 OK 成功处理了请求
- 204 No Content 请求处理成功,但没有资源可返回
- 206 Partial Content 请求资源的某一部分
- 3XX 重定向状态码
- 301 永久性重定向,表示请求的资源已被分配了新的 URI,比如启用了新域名、服务器切换到了新机房、网站目录层次重构,这些都算是“永久性”的改变。响应的 Location 首部中应该包含 资源现在所处的 URL
- 302 临时性重定向,资源的 URL 已临时定位到其他位置,客户端应该使用 Location 首部给出的 URL 来临时定位资源。将来的请求仍应使用老的 URL
- 303 告诉客户端应该用另一个 URL 获取资源
- 304 表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况
- 4XX 客户端错误状态码
- 400 表示请求报文中存在语法错误
- 401 未授权,客户端没有带认证信息或者带了错误的认证信息, 这时客户端可以修改认证信息进行重试
- 403 服务器拒绝了请求,客户端带了正确的认证信息, 但服务器认为这个认证信息对应的用户是没有对应资源的访问权限的, 因此, 在向管理员获取相关权限之前, 是没有重试的必要的
- 404 服务器无法找到所请求的 URL
- 5XX 服务器错误状态码
- 500 内部服务器错误
- 502 错误网关
- 503 服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
- 504 响应超时
HTTP1.0 和 HTTP1.1 和 HTTP2.0 的区别
超文本传输协议(HTTP)用于浏览器与服务器之间的通信
HTTP1.0 和 HTTP1.1
- 缓存处理:
- 1.0 的 header 中主要是通过 If-Modified-Since(比较资源的最后的更新时间是否一致),expires(资源的过期时间,取决于客户端本地时间)
- 1.1 引入了其他的 If-Match(比较 ETag 是否一致), If-None-Match(比较 ETag 是否不一致), If-Unmodified-Since(比较资源最后的更新时间是否不一致), Entity tag(资源的匹配信息)
- 带宽优化
- 1.0 存在一些浪费带宽的现象,例如客户端只需要某个对象的一部分,但是服务器将整个对象返回。
- 1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content)
- Host 头处理
- 1.0 中认为每个服务器都有一个唯一的 Ip,因此请求的 url 中并没有传递主机名(hostname)
- 随着虚拟化技术的发展,一台物理机上可以有多个虚拟机,共享同一个 ip,1.1 中的请求消息和响应消息都支持 Host,请求消息中如果没有 Host 头域会报告一个错误(400 Bad Request)
- 长连接
- http 是基于 TCP/IP 协议的,创建一个 TCP 连接是需要经过三次握手的,有一定的开销,如果每次通讯都要重新建立连接的话,对性能有影响。因此最好能维持一个长连接,可以用个长连接来发多个请求。
- 1.0 中每次需要使用 keep-alive 参数来告知服务器端要建立一个长连接
- 1.1 默认支持长连接,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点
- 新增状态码
- 1.1 中新增了 24 个错误状态响应码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除
- 新增请求方式
- PUT,DELETE,OPTIONS 等
http2.0 与 http1.X 区别
- header 压缩: header 头部带有大量的信息,而且每次使用报头压缩,降低开销,对于相同的 header 数据,不再通过每次请求和响应发送,差量更新 HTTP 头部,既避免了重复 header 的传输,又减小了需要传输的大小
- 多路复用:在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序
- 二进制分帧:消息由一个或多个帧组成。多个帧之间可以乱序发送
- 服务端推送:HTTP2 引入服务器推送,允许服务端推送资源给客户端,服务器会顺便把一些客户端需要的资源一起推送到客户端
HTTP 与 HTTPS 的区别
- HTTP 传输的数据都是未加密的,也就是明文的,HTTPS 协议是由 HTTP 和 SSL 协议构建的可进行加密传输和身份认证的网络协议,比 HTTP 协议的安全性更高。
- HTTPS 协议需要 CA 证书;
- 使用不同的链接方式,端口也不同,一般而言,HTTP 协议的端口为 80,HTTPS 的端口为 443;
HTTPS 协议的工作原理
- 客户使用 HTTPS URL 访问服务器,则要求 web 服务器建立 SSL 链接,客户端向服务器发送的报文包括客户端所支持的 ssl 版本,支持的加密算法以及密钥的长度。
- web 服务器接收到客户端的请求之后,也在报文中包含 SSL 版本以及加密组件,服务器的加密组件内容时从接收到的客户端加密组件内筛选出来的。
- 同时,web 服务器会将网站的 CA 证书(证书中包含了公钥),返回给客户端。
- 客户端通过 CA 证书来验证服务端的身份,公钥是否有效,比如颁发机构,过期时间,并随机生成对称加密的密钥 X 用公钥加密发给服务端。
- 服务器拿到客户端发过来的加密内容用自己的私钥解密获取到密钥 X。
- 双方都拿到了密钥 X,SSL 通道建立完成,通过密钥 X 加密信息来进行通信。 总结:HTTPS 协议使用了非对称加密 + 对称加密的方式,即利用了非对称加密安全性高的特点,又利用了对称加密速度快,效率高的好处
TCP 和 UDP 之间的区别
TCP:传输控制协议 UDP:用户数据报协议
- TCP 是面向连接的,UDP 是无连接的即发送数据前不需要先建立链接;
- TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。
- TCP 是面向字节流,UDP 面向报文;
- TCP 只能是 1 对 1 的,UDP 支持 1 对 1,1 对多;
- TCP 的首部较大为 20 字节,而 UDP 只有 8 字节;
TCP 的三次握手
参考链接:TCP 的三次握手
- 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 SN(c)。此时客户端处于 SYNSend 状态。
- 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s),同时会 把客户端的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 _SYN_REVD 的状态。
- 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了 服务端的 SYN 报文,此时客户端处于 establised 状态。
- 服务器收到 ACK 报文之后,也处于 establised 状态,此时,双方以建立起了链接。
- 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
- 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
- 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
- 如果没有第三次握手,就会出现一些丢包的情况,如果只握手 2 次,第二次握手时如果服务端发给客户端的确认报文段丢失,此时服务端已经准备好了收发数(可以理解服务端已经连接成功)据,而客户端一直没收到服务端的确认报文,所以客户端就不知道服务端是否已经准备好了(可以理解为客户端未连接成功),这种情况下客户端不会给服务端发数据,也会忽略服务端发过来的数据。如果是三次握手,即便发生丢包也不会有问题,比如如果第三次握手客户端发的确认 ack 报文丢失,服务端在一段时间内没有收到确认 ack 报文的话就会重新进行第二次握手,也就是服务端会重发 SYN 报文段,客户端收到重发的报文段后会再次给服务端发送确认 ack 报文。
TCP 的四次挥手
刚开始双方都处于 establised 状态,假如是客户端先发起关闭请求,则:
- 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
- 第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
- 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
- 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
- 服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
信息
为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。这其中的原因就是,要确保服务器是否已经收到了我们的 ACK 报文,如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。
对称加密和非对称加密的区别
密钥
- 对称加密:使用同一个密钥进行加密和解密。这意味着加密方和解密方必须事先共享同一个密钥,并且保证这个密钥的安全。
- 非对称加密:使用一对密钥,一个公开密钥(公钥)用于加密,一个私有密钥(私钥)用于解密。公钥可以公开分享,而私钥必须保持私密。
加密速度
- 对称加密:通常更快,因为它使用较简单的算法来处理大量数据。
- 非对称加密:由于其复杂的数学运算,尤其是在处理大量数据时,比对称加密慢得多。
安全性
- 对称加密:虽然对称加密算法通常很难破解,但密钥的管理和分发过程可能导致安全漏洞。
- 非对称加密:提供了更高的安全性,因为即使公钥被公开,没有私钥也无法解密信息。不过,实现上更为复杂,需要更小心地保护私钥。
使用场景
- 对称加密:适用于需要快速处理大量数据的场景,如文件加密、数据库加密、网络数据传输加密等。
- 非对称加密:常用于安全敏感的通信中,如数字签名、SSL/TLS证书验证、安全电子邮件等。由于其速度较慢,通常用于加密少量数据或用于加密对称加密中使用的密钥。
典型算法
- 对称加密算法:AES(高级加密标准)、DES(数据加密标准)、3DES(三重数据加密算法)、RC4等。
- 非对称加密算法:RSA、ECC(椭圆曲线密码学)、Diffie-Hellman密钥交换协议、ElGamal等。
WebSocket 协议
参考链接:HTML5 WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每 1 秒),由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
应用场景:实现即时通讯:如股票交易行情分析、聊天室、在线游戏等,替代轮询和长轮询
什么是浏览器的同源政策
信息
一个域下的 js 脚本在未经允许的情况下,不能够访问另一个域的内容。这里的同源的指的是两个域的协议、域名、端口号必须相同,否则则不属于同一个域。
同源政策主要限制了三个方面
- 第一个是当前域下的 js 脚本不能够访问其他域下的 cookie、localStorage 和 indexDB。
- 第二个是当前域下的 js 脚本不能够操作访问其他域下的 DOM。
- 第三个是当前域下 ajax 无法发送跨域请求。
同源政策的目的主要是为了保证用户的信息安全,它只是对 js 脚本的一种限制,并不是对浏览器的限制,对于一般的 img、或者 script 脚本请求都不会有跨域的限制,这是因为这些操作都不会通过响应结果来进行可能出现安全问题的操作。
HTTP 请求的方式
- GET:请求指定的页面信息,并返回实体主体。
- HEAD:类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
- POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
- PUT:从客户端向服务器传送的数据取代指定的文档的内容。
- DELETE:请求服务器删除指定的页面。
- CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
- OPTIONS:允许客户端查看服务器的性能。
- TRACE:回显服务器收到的请求,主要用于测试或诊断。
GET 和 POST 的区别
两者本质上都是 TCP 链接
- get 参数通过 url 传递,post 放在请求体 (request body) 中。
- get 请求在 url 中传递的参数是有长度限制的(该限制是由浏览器和服务器限制的),而 post 没有。
- get 请求只能进行 url 编码,而 post 支持多种编码方式。
- get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
- get 产生一个 TCP 数据包;post 产生两个 TCP 数据包。 对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据); 而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
浏览器输入 URL 之后发生了什么
- DNS 解析
- TCP 连接
- 发送 HTTP 请求
- 服务器处理请求并返回 HTTP 报文
- 浏览器解析渲染页面
- 连接结束
DNS 的具体过程
- 输入 IP,此时电脑发送一个 DNS 请求到本地 DNS 服务器(一般是网络接入服务商提供 eg:电信,移动)
- 本地 DNS 服务器会首先查询它的缓存记录,若有,则直接返回结果,若没有,本地 DNS 服务器还要向 DNS 根服务器进行查询;
- DNS 根服务器没有记录具体域名和 IP 地址的对应关系,而是告诉本地 DNS 服务器,可到域服务器上继续查询,并给出域服务器地址
- 本地服务器继续向域服务器发出请求,返回域名的解析服务器地址
- 本地 DNS 向域名解析服务器发出请求,收到域名与 IP 地址对应关系
- 本地 DNS 服务器将 IP 地址返回电脑,且保存副本到缓存已备下次查询
DNS 解析过程
1. 浏览器缓存
- 当用户在浏览器中输入一个网址时,浏览器首先检查自己的缓存,看看该域名的IP地址是否已经保存在本地。如果找到了相应的记录,DNS解析过程就此结束。
2. 系统缓存
- 如果浏览器缓存中没有找到,操作系统会检查自己的DNS缓存中是否有这个域名对应的IP地址。Windows系统可以通过命令
ipconfig /displaydns
来查看本地DNS缓存内容。
3. 路由器缓存
- 如果操作系统缓存中也没有记录,请求会被发送到路由器,路由器通常会有自己的DNS缓存。
4. ISP的DNS服务器
- 如果之前的步骤都未能解析域名,那么查询请求会被发送到ISP(互联网服务提供商)的DNS服务器。ISP的DNS服务器会检查它的缓存,看看是否可以找到这个域名对应的IP地址。
5. 根DNS服务器
- 如果ISP的DNS服务器也无法解析,它会向根DNS服务器发起请求。根服务器是顶级的DNS服务器,它不直接知道域名的IP地址,但能指引下一步应该查询哪个顶级域(TLD,例如
.com
、.net
等)服务器。
6. 顶级域(TLD)服务器
- 根据根服务器的指引,ISP的DNS服务器接着向适当的TLD服务器发送查询请求。TLD服务器管理着在该顶级域下注册的所有域名的信息,并能提供存储该域名记录的权威DNS服务器的地址。
7. 权威DNS服务器
- 最后,ISP的DNS服务器会向该域名的权威DNS服务器发起请求。权威服务器直接包含了映射到该域名的IP地址的记录。
8. 缓存结果并返回给客户端
- 一旦ISP的DNS服务器收到权威DNS服务器提供的IP地址,它会缓存这个结果(以便于未来加速同一域名的解析),然后把这个IP地址返回给最初发起请求的客户端(用户的计算机)。
9. 浏览器访问网站
- 浏览器最终收到IP地址后,就可以使用该地址与目标服务器建立连接,并开始加载网站内容。
DNS 域名缓存是什么?
缓存目的和好处
DNS域名缓存的主要目的是减少对远端DNS服务器的查询次数,加快域名解析速度,减轻DNS服务器的负担,从而提高整个互联网的效率和性能。具体来说,DNS缓存带来的好处包括:
- 提高解析速度:通过从缓存中直接获取解析结果,避免了每次都进行完整的DNS解析流程,大大加快了域名到IP地址的转换速度。
- 减少网络延迟:由于减少了对远端DNS服务器的查询,从而降低了网络延迟。
- 减轻DNS服务器负担:缓存可以显著减少DNS服务器接收的请求数量,有助于缓解服务器负载。
缓存位置
- 浏览器缓存:现代Web浏览器都会维护自己的DNS缓存,以便重复访问的网站可以更快加载。
- 操作系统缓存:操作系统也会缓存DNS查询结果,当应用程序请求DNS解析时,首先会检查操作系统的DNS缓存。
- 递归DNS服务器缓存:当用户的查询请求发送到递归DNS服务器时,这些服务器也会缓存一份DNS查询结果,供后续相同的查询请求使用。
- 权威DNS服务器:虽然权威DNS服务器本身不缓存外部域名的解析结果,但它们会为自己负责的域名提供TTL(生存时间),告诉其他DNS服务器和客户端可以缓存解析结果的时间长度。
Cookie 和 WebStorage(SessionStorage 和 LocalStorage)的区别
- 都会在浏览器端保存,有大小限制,同源限制
- cookie 会在请求时发送到服务器,作为会话标识,服务器可修改 cookie;web storage 不会发送到服务器
- cookie 有 path 概念,子路径可以访问父路径 cookie,父路径不能访问子路径 cookie
- 有效期:cookie 在设置的有效期内有效,默认为浏览器关闭;sessionStorage 在窗口关闭前有效;localStorage 长期有效,直到用户删除
- 作用域不同 sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localStorage:在所有同源窗口都是共享的;cookie:也是在所有同源窗口中共享的
- 存储大小不同:cookie 数据不能超过 4K;webStorage 虽然也有存储大小的限制,但是比 cookie 大得多,可以达到 5M 或更大
Cookie 和 Session 的区别
1.存储位置不同:
cookie 数据存放在客户的浏览器上
session 数据放在服务器上。
2.存储容量不同:
单个 cookie 保存的数据不能超过 4K,一个站点最多保存 20 个 cookie。
对于 session 来说并没有上限,但出于对服务器端的性能考虑,session 内不要存放过多的东西,并且设置 session 删除机制。
3.存储方式不同:
cookie 中只能保管 ASCII 字符串,并需要通过编码方式存储为 Unicode 字符或者二进制数据。
session 中能够存储任何类型的数据,包括且不限于 string,integer,list,map 等。
4.隐私策略不同
cookie 对客户端是可见的,别有用心的人可以分析存放在本地的 cookie 并进行 cookie 欺骗,所以它是不安全的。
session 存储在服务器上,不存在敏感信息泄漏的风险。
5.有效期不同
cookie 保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie 是很好的选择。
session 是保管在服务器端的,每个用户都会产生一个 session。假如并发访问的用户十分多,会产生十分多的 session,耗费大量的内存。
能设置或读取子域的 cookie 吗
不行! 只能向当前域或者更高级域设置 cookie
例如 client.com 不能向 a.client.com 设置 cookie, 而 a.client.com 可以向 client.com 设置 cookie
读取 cookie 情况同上
客户端设置 cookie 与服务端设置 cookie 有什么区别
无论是客户端还是服务端, 都只能向自己的域或者更高级域设置 cookie,例如 client.com 不能向 server.com 设置 cookie, 同样 server.com 也不能向 client.com 设置 cookie
服务端可以设置
httpOnly: true
, 带有该属性的 cookie 客户端无法读取客户端只会带上与请求同域的 cookie, 例如 client.com/index.html 会带上 client.com 的 cookie,server.com/app.js 会带上 server.com 的 cookie, 并且也会带上 httpOnly 的 cookie
同域/跨域 ajax 请求到底会不会带上 cookie
fetch 在默认情况下, 不管是同域还是跨域 ajax 请求都不会带上 cookie, 只有当设置了 credentials 时才会带上该 ajax 请求所在域的 cookie, 服务端需要设置响应头
Access-Control-Allow-Credentials: true
, 否则浏览器会因为安全限制而报错, 拿不到响应axios 和 jQuery 在同域 ajax 请求时会带上 cookie, 跨域请求不会, 跨域请求需要设置
withCredentials
和服务端响应头Access-Control-Allow-Credentials
fetch 设置 credentials 使 fetch 带上 cookie
jsfetch(url, { credentials: 'include', // include, same-origin, omit });
axios 设置 withCredentials 使 axios 带上 cookie
jsaxios.get('http://server.com', { withCredentials: true });
jQuery 设置 withCredentials
js$.ajax({ method: 'get', url: 'http://server.com', xhrFields: { withCredentials: true, }, });
前端攻击技术
XSS 攻击(cross-site script)
XSS 攻击形式:
主要是通过 html 标签注入,篡改网页,插入恶意的脚本,前端可能没有经过严格的校验直接就进到数据库,数据库又通过前端程序又回显到浏览器
js例如一个留言板: 如果内容是 hello!<script type="type/javascript src="恶意网址"></script> 这样会通过前端代码来执行js脚本,如果这个恶意网址通过cookie获得了用户的私密信息,那么用户的信息就被盗了
攻击的目的:
攻击者可通过这种方式拿到用户的一些信息,例如 cookie 获取敏感信息,甚至自己建网站,做一些非法的操作等;或者,拿到数据后以用户的身份进行勒索,发一下不好的信息等。
攻击防御
方法 1:cookie 中设置 HttpOnly 属性
方法 2:首先前端要对用户输入的信息进行过滤,可以用正则,通过替换标签的方式进行转码或解码,例如<> 空格 & '' ""等替换成 html 编码
jshtmlEncodeByRegExp:function (str){ var s = ""; if(str.length == 0) return ""; s = str.replace(/&/g,"&"); s = s.replace(/</g,"<"); s = s.replace(/>/g,">"); s = s.replace(/ /g," "); s = s.replace(/\'/g,"'"); s = s.replace(/\"/g,"""); return s; }
CSRF 攻击(cross site request forgery,跨站请求伪造)
CSRF 攻击形式:
CSRF 也是一种网络攻击方式,比起 xss 攻击,是另外一种更具危险性的攻击方式,xss 是站点用户进行攻击,而 csrf 是通过伪装成站点用户进行攻击,而且防范的资源也少,难以防范
csrf 攻击形式:攻击者盗用用户的身份信息,并以用户的名义进行发送恶意的请求等,例如发邮件,盗取账号等非法手段
信息
例如:你登录网站,并在本地种下了cookie 如果在没退出该网站的时候 不小心访问了恶意网站,而且这个网站需要你发一些请求等 此时,你是携带cookie进行访问的,那么你的种在cookie里的信息就会被恶意网站捕捉到,那么你的信息就被盗用,导致一些不法分子做一些事情
攻击防御:
验证 HTTP Referer 字段
信息
在HTTP头中有Referer字段,他记录该HTTP请求的来源地址,如果跳转的网站与来源地址相符,那就是合法的,如果不符则可能是csrf攻击,拒绝该请求
在请求地址中添加 token 并验证
信息
这种的话在请求的时候加一个token,值可以是随机产生的一段数字, token是存入数据库之后,后台返给客户端的,如果客户端再次登录的时候, 后台发现token没有,或者通过查询数据库不正确,那么就拒绝该请求
如果想防止一个账号避免在不同的机器上登录,那么我们就可以通过token来判断, 如果a机器登录后,我们就将用户的token从数据库清除,从新生成, 那么另外一台b机器在执行操作的时候,token就失效了,只能重新登录,这样就可以防止两台机器登同一账号
在 HTTP 头中自定义属性并验证
javascript// 如果说通过每次请求的时候都得加token那么各个接口都得加很麻烦, // 那么我们通过http的请求头来设置token // 例如: $.ajax({ url: '/v1/api', dataType: 'json', data: param, type:'post', headers: {'Accept':'application/json','Authorization':tokenValue} success:function(res){ console.log(res) } })
浏览器缓存机制
参考链接:HTTP 强缓存和协商缓存
浏览器缓存分为:强缓存和协商缓存
在浏览器第一次发起请求时,本地无缓存,向 web 服务器发送请求,服务器起端响应请求,浏览器端缓存。在第一次请求时,服务器会将页面最后修改时间通过 Last-Modified 标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个 Etag,并发送给客户端。
根据上图,浏览器在第一次请求发生后,再次发送请求时:
- 浏览器请求某一资源时,会先获取该资源缓存的 header 信息,然后根据 header 中的 Cache-Control 和 Expires 来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的 header 的信息,所以此次请求不会与服务器进行通信。这里判断是否过期,则是强缓存相关。
- 如果显示已过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的 header 字段信息,比如客户端会通过 If-None-Match 头将先前服务器端发送过来的 Etag 发送给服务器,服务会对比这个客户端发过来的 Etag 是否与服务器的相同,若相同,就将 If-None-Match 的值设为 false,返回状态 304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将 If-None-Match 的值设为 true,返回状态为 200,客户端重新请求服务器端返回的数据;客户端还会通过 If-Modified-Since 头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回 304,客户端继续使用本地缓存。
强缓存 Expires 和 Cache-Control 的使用
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的,用来表示资源的缓存时间。强缓存中,普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上Cache-Control:no-cache
和 Pragma:no-cache
Expires
Expires 的值是一个绝对时间的 GMT 格式的时间字符串。比如 Expires 值是:expires:Fri, 14 Apr 2017 10:47:02 GMT
。这个时间代表这这个资源的失效时间,只要发送请求时间是在 Expires 之前,那么本地缓存始终有效,则在缓存中读取数据。
缺点: 由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,误差很大,就会导致缓存混乱。
Cache-Control
Cache-Control 主要是利用该字段的 max-age
值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600
,代表着资源的有效期是 3600 秒。
cache-control 除了该字段外,还有下面几个比较常用的设置值:
- no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在 ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
- public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。
- private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。
Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。如:
cache-control:max-age=691200
expires:Fri, 15 May 2020 10:47:02 GMT
那么表示资源可以被缓存的最长时间为 691200 秒。
协商缓存
协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。
Etag 和 If-None-Match
Etag/If-None-Match
返回的是一个校验码。Etag
可以保证每一个资源是唯一的,资源变化都会导致Etag
变化。服务器根据浏览器发送的If-None-Match
值来判断是否命中缓存。
与Last-Modified
不一样的是,当服务器返回 304 (Not Modified) 的响应时,由于Etag
重新生成过,response header 中还会把这个Etag
返回,即使这个Etag
跟之前的没有变化。
Last-Modify / If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify,Last-Modify 是一个时间标识该资源的最后修改时间,例如 Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回 Last-Modify。服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify。
为什么要有 Etag
两个都可以确定缓存资源的是否可用,有什么区别呢?
Etag
的出现主要是为了解决几个 Last-Modified
比较难解决的问题:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说 1s 内修改了 N 次),
If-Modified-Since
能检查到的力度是秒级的,这种修改无法判断; - 某些服务器不能精确的得到文件的最后修改时间。
Last-Modified
与 ETag
是可以一起使用的,服务器会优先验证ETag
,一致的情况下,才会继续比对 Last-Modified
,最后才决定是否返回 304。
进程与线程的区别
官网定义:
进程是系统进行资源分配和调度的基本单位
线程是操作系统能够进行运算调度的最小单位
简单理解:
- 进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。
- 线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。
阮一峰老师的解释
- 计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。
- 假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
- 进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
- 一个车间里,可以有很多工人。他们协同完成一个任务。
- 线程就好比车间里的工人。一个进程可以包括多个线程。
- 车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
- 可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。 这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
- 一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。 这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
- 还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。
- 这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。 这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。
操作系统的设计,因此可以归结为三点:
- 以多进程形式,允许多个任务同时运行;
- 以多线程形式,允许单个任务分成不同的部分运行;
- 提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。