思维导图
1. 网络协议
1.1 OSI 7层模型
- 开放式系统互联模型
- 世界范围内的网络标准概念模型
- OSI 的努力让互联网协议逐渐走向标准化
下图为 OSI 7层模型:
分层架构:
- 分层架构的好处是将应用分成N层,替换其中一层不影响其它层的工作,不需要重构整个应用;
- 分层的设计要点:
- 必要性/独立性/可替换
- 层的颗粒度
- 数据的可追溯性
小结
- OSI 是概念模型,同时也是标准;
- 『分层』是最常见的架构手段
- TCP/IP 协议群受到 OSI 的影响。
1.2 TCP/IP 协议和互联网协议群
TCP/IP 四层模型
TCP/IP 封包
1.3 DNS 和 CDN
统一资源定位URL,也称作网址:
1.3.1 DNS
推荐文章:DNS原理入门
DNS (Domain Name System 的缩写)的作用非常简单,就是根据域名查出IP地址。你可以把它想象成一本巨大的电话本。
举例来说,如果你要访问域名math.stackexchange.com,首先要通过DNS查出它的IP地址是151.101.129.69。
图解:当用户在浏览器中输入 www.baidu.com 的时候,第一个要思考的问题是 www.baidu.com 在哪里?而这个问题就要问 DNS 服务,DNS 域名系统返回 www.baidu.com 对应的IP 是 220.181.38.150,然后浏览器拿着这个 IP 地址去请求百度,这个IP地址对应的就是百度的服务,百度最终返回内容给浏览器。
DNS 解析过程:浏览器缓存 -> 操作系统缓存 -> 操作系统 host 文件 -> dns 服务器
而 dns 服务器查找顺序为:非权威 dns 服务器 -> 根域名服务器 -> 顶级域名服务器 -> 二级域名服务器
1.3.2 DNS相关名词解释
- A记录 - 定义主机的IP地址 (A:address IN:internet)
// 定义www.example.com的ip地址
www.example.com. IN A 139.18.28.5;
- AAAA记录 - 定义主机的IPv6地址
// 定义www.zhihu.com的ipv6地址
1111222222.s2txipv6.cdntip.com.103 IN AAAA 240e:940:401:1:1a::
- CNAME记录 (Canonical Name Record) - 定义域名的别名
// 定义www.example.com的别名
www.example.com. IN CNAME example.com.
a.example.com. IN CNAME b.example.com.
www.foo.com. IN CNAME example.com.
- MX 记录 (Mail exchanger record) - 定为邮件服务器
// happy.example.com 作为邮件服务域名
IN MX happy.example.com.
// A记录描述邮件服务器IP
happy.example.com. IN A 123.123.123.122;
- NS 记录 (Name Server Record) - 定义提供dns信息的服务器
// 定义为 zhihu.com 提供dns信息的服务器
zhihu.com 52908 IN NS ns4.dnsv5.com.
zhihu.com 52908 IN NS ns3.dnsv5.com.
- SOA 记录 (Start of Authority Record) - 定义在多个ns服务器中哪个是主服务器
// ns3.dnsv5.com. 是主服务器
IN SOA ns3.dnsv5.com. enterprise3dnsadmin.dnspod.com. 1594718785 3600180 1209600180
- TXT 记录 - 提供文本信息
// zhihu.com 提供的文本信息
zhihu.com. 600 IN TXT "goole-site-verification=jsjsjjshhhdhdhhdhudhahahhah"
zhihu.com. 600 IN TXT "v=spf1 include:_spf.google.com include:cust-spf.edmsphere.com -all"
1.3.3 实战 DNS 工具
- window/linux/mac 等下的 host 文件修改
- Switchhost 工具
1.3.4 CDN - 内容分发网络(Content Delivery Network)
基于地理位置的分布式代理服务器/数据中心。
- 提供高可用
- 提升性能
- 提升体验
CDN实现原理如下图:
当用户输入一个网址,浏览器会检查这个网址上的所有的资源的请求,比如JS、css等都要去拿请求,我们以一个js文件为例,浏览器发起一次js请求,
首先会做DNS查询,查询这个js文件所在的ip地址,通常接了cdn的话,查回来的结果不是真的ip地址,而是返回一个CNAME记录(域名别名,如图1283werf.cdnxxx.com);
然后浏览器又去查这个别名,查到的结果是cdn智能dns服务的一个ip地址;
所以现在浏览器到智能调度DNS中心去查找这个js文件,智能调度DNS中心通常会返回离你较近的节点的ip地址。
如果智能调度DNS发现这个js文件没有,它会去真正的服务器那里获取内容,这个过程叫做CDN回源。如果所有的静态资源都缓存在这些节点上了,那就没有回源这个过程了。
通常cdn用来存变化不大的资源,另外cdn支持删除某个文件,但是一般采取替换文件的做法,比如将某张绿色图片改为红色图片,通常不是删除所有节点上的绿色图片,而是替换这个文件。
1.3.5 CDN 云测工具
云测工具有很多,比如 cdn.chinaz.com/
从百度的控制台 Network中复制一张图片dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/footer/aria-3006e33cce.png
去云测工具中查询一下,能看到cdn的信息。
1.4 HTTP 入门和基础工具链
1.4.1 HTTP 协议
- 超文本传输协议
- 处理客户端和服务端之间的通信
- http请求/http返回
- 网页/json/xml/提交表单...
HTTP 协议是纯文本 + 无状态 的协议:
- HTTP 是应用层协议
- 信息纯文本传输
- 无状态 (每次请求独立、请求间互不影响)
- 浏览器提供了手段来维护状态(Cookie、Session、LocalStorage、SessionStorage等)
HTTP 协议设计的基础因素:
- 带宽 (基础网络,如线路、设备等)
- 延迟 (如浏览器延迟、DNS查询时间、TCP三次握手建立连接的时间等)
HTTP 协议设计考虑因素 --缓存与带宽优化:
- 缓存
- http1.0提供缓存机制如IF-Modified-Since等基础缓存控制策略
- http1.1提供E-Tag等高级缓存策略
- 带宽优化
- http1.1利用range头获取文件的某个部分
- http1.1利用长连接让多个请求在一个TCP连接上排队
- http2.0利用多路复用技术同时传输多个请求
HTTP 协议设计考虑因素 --压缩/安全性:
- 压缩
- 主流web服务器如nginx/express等提供gzip压缩功能
- http2.0采用二进制传输,头部使用 HPACK 算法压缩
- HTTPS
- 在 HTTP 和 TCP/IP 之间增加 TSL/SSL 层
- 数据传输加密(非对称 + 对称加密)
1.4.2 HTTPS
- 安全超文本传输协议
- 数据加密传输 (防止各种攻击手段,如信息泄露、篡改等)
- SSL/TSL
- SSL -安全套接字
- TSL -传输层安全协议(TSL更安全)
- 需要在客户端安装证书
1.4.3 Header 和 Body
- HTTP 协议是一个文本传输协议,传输内容是人类可读的文本,大体分成两部分:
- 请求头/返回头 (Header)
- 消息体 (Body) 具体字段可见浏览器控制台。
1.4.4 Chrome 浏览器
- Google 开发的免费浏览器
- Chrome 开发者工具拥有强大的调试能力
1.4.5 curl 命令行工具
curl: 传输一个URL(和服务器交互的命令行工具) 支持很多种协议,如HTTP/HTTPS/FTP/FTPS/SCP/SCFP/DICT/TELNET...
curl https://www.baidu.com
curl -I https://www.baidu.com
1.4.6 抓包工具 Whistle
跨平台网络调试工具
- 需要SwitchOmega插件
- node.js开发
- 支持抓包、重放、替换、修改等
npm install whistle -g
装好之后,去localhost就能看到界面。具体操作请自行搜索资料。
1.5 HTTP 协议详情详解
1.5.1 请求方法
- GET 从服务器获取资源
- POST 在服务器创建资源
- PUT 在服务器修改资源
- DELETE 在服务器删除资源
- OPTION 与跨域相关
- TRACE 用于显示调试信息(多数网站不支持,怕泄露信息)
- CONNECT 与代理相关
- PATCH 对资源进行部分更新(极少用)
1.5.2 状态码
- 1xx: 提供信息 (100 continue 101 切换协议)
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务端错误
// 2xx 状态码
200-OK
201- Created 已创建
202-Accepted 已接收
203-Non-Authoritative Infomation 非权威内容
204-No Content 没有内容
205-Reset Content 重置内容
206-Partial Content 服务器下发了部分内容(range header)
注:多数服务端开发已经不遵循状态码了。
// 3xx 重定向
300-用户请求了多个选项资源(返回选项列表)
301-moved Permanently 永久转移
302-资源被找到(以前是临时重定向)
303-See Other 可以使用GET方法在另一个URL找到资源
304-not modified 没有修改(缓存部分特别说明)
305-use Proxy 需要代理
307-临时重定向
308-永久重定向
// 4xx 客户端错误
400-Bad Request 请求格式错误
401-Unauthorized 没有授权
402-Payment Required 请先付费
403-Forbidden 禁止访问
404-Not Found 没有找到
405-Method Not Allowed 请求方法不被允许
406-Not Acceptable 服务端可以提供的内容和客户端期待的不一样
注:多数服务端开发已经不遵循状态码了。
// 5xx 服务端错误
500- Internal Server Error 内部服务器错误
501-Not Implemented 没有实现
502-Bad Gateway网关错误
503-Service Unavailable 服务不可用
504-Gateway Timeout 网关超时
505-HTTP Version Not Supported 版本不支持
注:多数服务端开发已经不遵循状态码了。
1.5.3 问题集合
问题1:301 VS 308
共同点:资源被永久转移到新的地址
差异:
- 客户端收到308请求后,之前是什么method,之后也会延用这个method(POST/GET/PUT)到新的地址
- 客户端收到301请求后,通常用户会向新地址发起GET请求
问题2:302/303/307
共同点:资源临时放到新地址(请不要缓存) 差异:
- 302是http1.0提出的,最早叫moved Temporarily;很多浏览器实现的时候没有遵循标准,把所有请求都重定向为GET
- 1999年标准委员会增加了303和307,并将302重新定义为Found
- 303告诉客户端使用GET方法重定向资源
- 307告诉客户端使用原请求的method重定向资源
1.5.4 头部字段解释
Content-Length
发送给接收者的Body内容长度(字节)
- 一个byte是8bit
- Utf-8编码的字符1-4个字节
User-Agent
帮助区分客户端特性的字符串,如操作系统、浏览器、制造商(手机类型)、内核类型、版本号等等
Content-Type
帮助区分资源的媒体类型(Media Type/MIME Type),如text/html、text/css、application/json、image/jpeg......
Origin
描述请求来源地址
- scheme://host:port
- 不含路径
- 可以是null
Accept
建议服务器返回何种媒体类型(MIME Type)
- */*代表所有类型(默认)
- 多个类型用逗号隔开,例如 text/html,application/json
Accept-Encoding:建议服务端发送哪种编码(压缩算法)
- deflate,gzip;q=1.0,*;q=0.5
Accept-Language:建议服务端传送哪种语言
- Accept-Language:fr-CH;q=0.9,en;q=0.8,de;q=0.7,*;q=0.5
Referer
告诉服务端打开页面的上一张页面的URL;如果是ajax请求那么告诉服务端发送请求的URL是什么
- 非浏览器环境有时候不发送Referer(或者是虚拟Referer,通常是爬虫)
- 常常用作用户行为分析
Connection
决定连接是否在当前事务完成后关闭
- Http1.0默认是false
- Http1.1后默认是 keep-alive
1.6 全栈角度看 HTTP 协议
- Body解析过程中的协商技巧很有用
- 认真对待3xx状态码
- 错误处理遵循HTTP协议
1.7 加密和 HTTPS 证书
1.7.1 算法
- DES
1970年IBM提出的对称加密算法,可暴力破解
-
AES
2001年美国国家标准与技术研究院发布的对称加密算法,由两位密码学家共同设计,可旁道攻击 -
RSA
1977年提出的非对称加密算法
1.7.2 对称和非对称 比较
- 非对称加密安全性更好
- 对称加密计算速度更快
- 通常是混合使用(利用非对称加密协商密钥,然后进行对称加密)
1.7.3 HTTPS 建立连接到工作的过程
三次握手和回传证书是不加密的,客户端密钥协商使用非对称加密,数据传输使用对称加密。
问题:如果现在的网络延迟是30ms,那我的HTTPS从发送第一条数据到服务端确认这条数据成功,最少需要多少时间?
30+160=190ms
1.8 UDP VS TCP,HTTP2.0 和 HTTP3.0
1.8.1 UDP VS TCP
如上图:主机到主机之间的通信是属于传输层的,网络层更像是物流公司,帮忙把数据从一个地址运送到另一个地址,数据也被拆分成片段了。
-
UDP 比 TCP 节省网络资源和迅速
- 不需要建立连接(延迟更低)
- 封包体积更小(传输速度快)
- 不关心数据顺序(不需要序列号和ACK,传输速度快)
- 不保证数据不丢失
-
UDP 和 TCP 连接比较
- UDP 和 TCP 的重发(校验)
- UDP 不保证顺序
- UDP 没有虚拟连接、不校验数据、不保证顺序、没有收到不重发
- 这样的UDP自由度更高......
- 需要用户程序在应用层定义类似的机制
- TCP 面向流(API接收流)、UDP面向消息(API接收数据包)
- 场景不同
- UDP和TCP的边界逐渐模糊:不管是传输文本&文件还是多媒体
- TCP:远程控制(远程登录的场景,使用TCP)
- UDP:DNS查询(DNS查询的场景使用UDP)
1.8.2 HTTP2.0
- 多个请求多路复用
- 防止队头阻塞
- 压缩HTTP头:HPACK技术
- 服务端推送
如上图,在HTTP1.1 中,多个文件共用一个TCP连接,就会有排队阻塞的问题。另外,在浏览器中,为了不过多占用资源,一次最多只能建立6个TCP连接,如果文件很多的话,也会造成队头阻塞问题。HTTP2.0的多路复用解决了这个排队阻塞问题,但是还是没能解决TCP层排队阻塞问题。
压缩头部:HPACK技术
1.8.3 HTTP3.0
总结
- UDP 把自由度给了用户,使用的人少;TCP自由度低,用的人多
- HTTP2.0/HTTP3.0 都兼容 HTTP1.1
2. 网络请求实战
2.1 RESTFUL约定和postman
REST,即Resource Representational State Transfer的缩写。意思是:“表现层状态转移”。
Resource:资源,即"数据",你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符;
Representational:某种表现形式–"资源"具体呈现出来的形式,比如用JSON,XML,JPEG等;
State Transfer:状态变化。通过HTTP动词实现(GET、POST、PUT、DELETE等)。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
RESTful API就是REST风格的接口,RESTful是一种软件架构风格,而不是标准。
GET/product?{query} // 查询产品
GET/product/123 // 查询某个产品
POST/product<body> // 新建产品
PUT/product/123<body> // 修改某个产品
DELETE/product/123 // 删除某个产品
RESTful的优点:
- 客户端无状态(简化开发)
- 资源独立、接口间独立(缓存好设计)
- 对协议依赖不严重(可迁移)
总结:
- 从restful角度看,前端不是无状态,而是无业务状态。
- mock数据和接口测试的方法除了postman,还有mock.js、mocha、jest等等。
2.2 Fetch 和 Promise
promise 代表异步请求求值的过程和结果 (pending、fufilled、rejected)
fetch 一个让处理 http pipeline 更容易的工具(MDN)
- 返回 promise
- Resolve发生在网络通信正常(404,500也认为是resolve)
- Reject 发生在网络通信异常
- 默认不接受 cookie,需要时可以设置(credentials:'include')
demo此处省略。
2.3 上传文件
- 上传文件和提交输入框的字段没有本质的区别
- Base64方法速度慢,没有特殊情况通常使用blob上传
2.4 WebSocket
WebSocket协议是一个基于TCP的通信协议
- 复用HTTP的握手
- 基于TCP传输协议
2.5 缓存和缓存清理
缓存:存储将被用到的数据,让数据访问更快
- 命中: 在缓存中找到了请求的数据
- 不命中/穿透:缓存中没有需要的数据
- 命中率:命中次数/总次数
- 缓存大小:缓存中一共可以存多少数据
- 清空策略:如果缓存空间不够数据如何被替换
Cache-Control:定义所有的缓存都要遵守的行为。
可缓存性:
- public:允许所有方缓存响应,允许客户端和服务器端都缓存
- private:只允许客户端(即浏览器)缓存响应
- no-cache:每次必须先询问服务器资源是否已经更新
- no-store:不使用缓存
缓存期限:
- max-age:秒(存储周期)max-age=30,缓存30s后就过期,需要重新请求
- s-maxage:秒(共享缓存如代理等,存储周期),覆盖max-age,作用一样,只在代理服务器中生效
强制缓存和协商缓存:
一 强制缓存
强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核心就是如何知道当前时间是否超过了过期时间。
强制缓存的过期时间通过第一次访问服务器时返回的响应头获取。在 http 1.0 和 http 1.1 版本中通过不同的响应头字段实现。
http 1.0
在 http 1.0 版本中,强制缓存通过 Expires 响应头来实现。 expires 表示未来资源会过期的时间。也就是说,当发起请求的时间超过了 expires 设定的时间,即表示资源缓存时间到期,会发送请求到服务器重新获取资源。而如果发起请求的时间在 expires 限定的时间之内,浏览器会直接读取本地缓存数据库中的信息(from memory or from disk),两种方式根据浏览器的策略随机获取。
http 1.1
在 http 1.1 版本中,强制缓存通过 Cache-Control 响应头来实现。Cache-Control 拥有多个值:
- private:客户端可以缓存
- public:客户端和代理服务器均可缓存;
- max-age=xxx:缓存的资源将在 xxx 秒后过期;
- no-cache:需要使用协商缓存来验证是否过期;
- no-store:不可缓存
最常用的字段就是 max-age=xxx ,表示缓存的资源将在 xxx 秒后过期。一般来说,为了兼容,两个版本的强制缓存都会被实现。
总结
强制缓存只有首次请求才会跟服务器通信,读取缓存资源时不会发出任何请求,资源的 Status 状态码为 200,资源的 Size 为 from memory 或者 from disk ,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。
二 协商缓存
协商缓存与强制缓存的不同之处在于,协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。
在 http 协议的 1.0 和 1.1 版本中也有不同的实现方式。
**http 1.0
**在 http 1.0 版本中,第一次请求资源时服务器通过 Last-Modified 来设置响应头的缓存标识,并且把资源最后修改的时间作为值填入,然后将资源返回给浏览器。在第二次请求时,浏览器会首先带上 If-Modified-Since 请求头去访问服务器,服务器会将 If-Modified-Since 中携带的时间与资源修改的时间匹配,如果时间不一致,服务器会返回新的资源,并且将 Last-Modified 值更新,作为响应头返回给浏览器。如果时间一致,表示资源没有更新,服务器返回 304 状态码,浏览器拿到响应状态码后从本地缓存数据库中读取缓存资源。
这种方式有一个弊端,就是当服务器中的资源增加了一个字符,后来又把这个字符删掉,本身资源文件并没有发生变化,但修改时间发生了变化。当下次请求过来时,服务器也会把这个本来没有变化的资源重新返回给浏览器。
http 1.1
在 http 1.1 版本中,服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存。
总结
协商缓存每次请求都会与服务器交互,第一次是拿数据和标识的过程,第二次开始,就是浏览器询问服务器资源是否有更新的过程。每次请求都会传输数据,如果命中缓存,则资源的 Status 状态码为 304 而不是 200 。同样的,一般来讲为了兼容,两个版本的协商缓存都会被实现,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。
-
每次发布新的静态资源的时候,如何更新缓存?
让文件名不同,比如加上时间戳 -
HTTP 缓存大小有限制吗?FIFO还是LRU?
有,如果发现缓存太大了,就会清理一些不常用的缓存。 用哪种算法需要结合具体场景来选择。
3. 网络安全与攻防
3.1 同源策略
同源策略:禁止一个源的脚本或文档和另一个源的脚本和文档进行交互。
- 两个url的protocol、port和host都相同,那么同源
问题1:为什么不禁用不同源的js?
我们需要使用很多的第三方插件,比如地图组件,而这些第三方的组件可能都不在你的域名下,和你不同源,甚至是一些cdn资源也是不同源的,所以不能禁用。
问题2:应不应该允许不同源的js修改dom? 允许
问题3:应不应该允许不同源的js获取远程图片内容?
图片资源相当于数据,如果不同源的脚本能执行获取数据的代码,那是相当危险的,不应该允许
问题4:应不应该允许网站提交数据到不同源的服务器?
不允许 不允许收集数据的
问题5:应不应该允许网站提交cookie到不同源的服务器?
不允许,除非有配置项或者是跨域
3.2 跨域的多种方法
3.2.1 JSONP
原理就是通过添加一个<script>标签,向服务器请求 JSON数据,这样不受同源政策限制。服务器收到请求 后,将数据放在一个callback回调函数中传回来。比如 axios。
不过只支持GET请求且不安全,可能遇到XSS攻击,不过它的好处是可以向老浏览器或不支持CORS的网站请求数据
let script = document.createElement('script');
script.type = ' text/javascript';
script.src = 'http://juejin.com/xxx?callback=handleCallback';
document.body.appendChild(script);
function handleCallback(res){
console.log(res);
}
服务器返回并立即执行
handleCallback({ code: 200z msg: 'success', data: [] });
3.2.2 CORS
CORS通信过程都是浏览器自动完成,需要浏览器(都支持)和服务器都支持,所以关键在于只要服务器支持,就可以跨域通信,CORS请求分两类,简单请求和非简单请求。另外CORS请求默认不包含Cookie以及HTTP认证信息,如果需要包含Cookie,需要满足几个条件:
- 服务器指定了 Access-Control-Allow-Credentials: true
- 开发者须在请求中打开 withCredentials 属性:xhr.withCredentials = true
- Access-Control-Allow-Origin不要设为星号,指定明确的与请求网页一致的域名,这样就不会把其他域名的Cookie上传。
简单请求
同时满足两个条件,就属于简单请求:
- 请求方法是:HEAD、GET、POST,三者之一;
- 请求头信息不超过以下几个字段: Accept Accept-Language Content-Language Last-Event-Id Content-Type: 值为三者之一,application/x-www-form-urlencoded、multipart/form-data、text/plain。
需要这些条件是为了兼容表单(form),因为历史上表单一直可以发出跨域请求。
浏览器直接发出CORS请求,具体来说就是在头信息中增加Origin字段,表示请求来源来自哪个域(协议+域名+端口),服务器根据这个值决定是否同意请求。如果同意,返回响应会多出以下响应头信息:
Access-Control-Allow-Origin: http://juejin.com // 和Origin一致,这个字段是必须的
Access-Control-Allow-Credentials: true // 表示是否允许发送Cookie 这个字段是可选的
Access-Control-Expose-Headers: FooBar // 指定返回其他字段的值 这个字段是可选的
Content-Type: text/html; charset=utf-8 // 表示文档类型
在简单请求中服务器至少需要设置:Access-Control-Allow-Origin 字段。
非简单请求
比如 PUT 或 DELETE 请求,或Content-Type 为 application/json,就是非简单请求。
非简单CORS请求, 正式请求前会发一次OPTIONS类型的查询请求,称为 预检请求,询问服务器是否支持网页所在域名的请求,以及可以使用哪些头信息字段。只有收到肯定的答复, 才会发起正式XMLHttpRequest请求, 否则报错。
预检请求的方法是OPTIONS, 它的头信息中有几个字段:
・Origin:表示请求来自哪个域,这个字段是必须的
• Access-Control-Request-Method:列出CORS请 求会用到哪些HTTP方法,这个字段是必须的
• Access-Control-Request-Headers:指定CORS 请求会额外发送的头信息字段,用逗号隔开,比如 'Access-Control-Request-Headers':'content-type,token'
OPTIONS请求次数过多也会损耗性能,所以要尽塔减少 OPTIONS请求,可以让服务器在请求返回头部添加
Access-Control-Max-Age: Number // 数字 单位是秒
表示预检请求的返回结果可以被缓存多久.在这个时间 范围内再请求就不需要预检了。不过这个缓存只对完全 一样的URL才会生效。
其他如代理等方法就不在此处详细记录了,见自己的有道笔记《前端怎么实现跨域请求》。
- 理解跨域要解决的问题而不是记住跨域这个现象和处理方法
- 子域名和父域名交互的时候因为子域名可以修改自己的域名为父域名可以解决跨域问题
- 理解策略要解决的问题,而不是记住处理的方法
- 决定用哪种策略核心原则是在安全的前提下获得最优效率
3.3 常见网络安全攻防
3.3.1 阻断服务攻击(Dos)
- 阻断服务攻击(Denial-of service attack),想办法将目标网络资源用尽
- 变种:分布式阻断服务攻击(Distributed Denial-of service)
一般分为两种:宽带消耗型(消耗目标的带宽)、资源消耗型(消耗目标的计算资源)
解决方法:防火墙、购买交换机(路由器)、购买流量清洗。
3.3.2 地址欺骗解析(Address Resolution Protocol spoofing)
地址解析协议欺骗是一种将伪造的ARP或地址解析协议消息发送到以太网局域网的策略。ARP欺骗的主要功能是将流量从一个IP地址重定向到欺诈发起方的MAC地址。该过程通过欺骗以太网来实现接收伪造地址和路由流量,以欺骗地址终止,而不是直接指向真正的IP地址。ARP欺骗的主要功能是将流量从IP地址重定向到MAC地址。
这种手段在今天主要用作调试了。
3.3.3 跨站脚本攻击
原理:将跨站脚本注入到被攻击的网页上,用户打开网页会执行跨站脚本。
你在网页的表单上填写信息时,一些黑客就会填写一段js脚本,提交数据,到服务器端存储,最后在其他网页上展示并执行了该脚本。
解决方法:输入时过滤或转义,服务端做转义,输出时做过滤或转义。
3.3.4 SQL 注入
在用户输入时,填写了一段sql语句,然后提交数据了,服务端如果没做处理,就会执行这段sql语句。
3.3.5 跨站请求伪造(csrf)
将转账链接挂到邮件或者别的地方的某个按钮或者某张图片上,当用户点击的时候,就会执行转账操作,钱就会被转走。
解决方法:改成 post 方式提交数据或者在表单的 input 上加属性 name="csrf"
3.3.6 HTTPS 中间人攻击
4. 浏览器状态同步和路由
4.1 前端路由和服务器端路由原理
4.1.1 History API
提供操作控制浏览器会话历史,维护会话栈(Session stack)的能力。
history.go()
history.back() 和 history.forward()
history.pushState(state,title,url)
history.replaceState(state,title,url)
4.2 Session Cookie Storage和单点登录
4.2.1 登录场景(理解Session和Cookie)
问题1:为什么不让用户每次输入用户名和密码?
麻烦,而且也不安全
问题2:为什么浏览器是无状态的?
前端用来展示资源的,本身是不存储数据的,所以浏览器是无状态的,用户状态存储在服务端。
4.2.2 cookie、localStorage、sessionStorage的区别?
4.2.3 Token (令牌)
Oauth
Oauth 是用户在互联网获取资源的开放(委托形式)授权标准。
OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。
OAuth允许用户提供一个令牌给第三方网站,一个令牌对应一个特定的第三方网站,同时该令牌只能在特定的时间内访问特定的资源。
假设你访问了一个网站,叫做A站。不要多想,很干净的站点。
你可以用QQ登录A站,而A站可以直接从QQ网站上获取你的头像,昵称,甚至QQ空间里的图片等信息。
这个故事里有三个角色:
你:作为资源(头像,图片等)的拥有者,就是Owner。
QQ:是资源的托管者,就是Resource Manager
A站:想要获取你的这些资源。
QQ不可能随便把你的资源给别人,不可能这么没良心的。当然没良心的公司多了去了,卖你的电话号码,身份证的公司多了去了。我们假设QQ不会这么干。
那么A站如何获取你的这些资源呢?
你可以把你的用户名和密码给A站,然后A站就可以去QQ哪里获取你的资源了。
如果你脑子还好,肯定不想这么干。
因为A站有可能第二天就把你的QQ号和密码卖给999家推销公司去了,还可能把你的图片放到某些网站上去了。
那怎么办呢?于是就有了oauth这个协议。
oauth就是:
你告诉QQ你授权A站访问你的部分资源而不用把密码给A站的一个权限代理协议。 类似下面的流程:
第一次拿许可,第二次拿令牌。那许可和令牌就用到了摘要算法。
如何保证Token唯一?
散列算法:sha(client_id + rnd + timestamp)
rnd:随机数 timestamp: 当前的时间戳
这样得出一个id,不重复的id,还可以根据id反查client_id。
4.2.4 单点登录 Single Sign On 简称SSO
单点登录:指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的系统。简而言之,多个系统,统一登录。
单点登录使用oauth协议去实现。
- Cookie/Session/Storage:状态同步
- Oauth:资源开放
- SSO:业务整合
4.3 SSR 和单页面应用的分析
4.3.1 单页面应用 single page web application,SPA
SPA的缺点:
- 浏览器的CPU开销大(组件vs时间) 需要渲染
- 流量开销大(一次加载多张页面)
- 需要好的系统架构
- 搜索引擎不友好
4.3.2 SSR 服务端渲染
SSR的优点:
- 显著减小TTI(Time To Interactive)
- 单页面应用SEO解决方案
- 内网数据组装
SSR的缺点:
- 服务器CPU压力大
- CDN不好支持
- 开发工作量大
- 全局对象失效
5. 工具链和其他
5.1 whistle
爬虫工具:whistle,有很强大的功能,具体见官网 wproxy.org/whistle/。
比较好用的功能是:
- 修改 Host (需要安装chrome插件:SwitchyOmega)
- proxy 代理
- 替换文件
- 替换 UA
- 远程调试
- js注入
5.2 web 服务器
web服务器的最核心能力就是提供 web server,就是用户发请求,它返回内容。
5.2.1 web 服务器具有 proxy 代理能力
正向代理为客户端服务。
反向代理为服务器端服务。正向代理和反向代理的区别是什么?
1、位置不同
正向代理,架设在客户机和目标主机之间;
反向代理,架设在服务器端;2、代理对象不同
正向代理,代理客户端,服务端不知道实际发起请求的客户端;
反向代理,代理服务端,客户端不知道实际提供服务的服务端;3、用途不同
正向代理,为在防火墙内的局域网客户端提供访问Internet的途径;
反向代理,将防火墙后面的服务器提供给Internet访问;4、安全性不同
正向代理允许客户端通过它访问任意网站并且隐藏客户端自身,因此必须采取安全措施以确保仅为授权的客户端提供服务;
反向代理都对外都是透明的,访问者并不知道自己访问的是哪一个代理。正向代理是客户端找代理,把自己的请求转发给服务端;而反向代理,则是服务端找代理,把自己接受到的请求转发给背后的其他机器。正向代理,代理服务器为客户端服务;反向代理,代理服务器为服务端服务。
5.2.2 web 服务器具有缓存能力
对一些不经常变化的数据或者内容,web服务器提供缓存功能。
5.2.3 web 服务器具有打印日志的能力
一般有两种日志,分别是:
- access——log:用户访问产生的日志;记录访问时间、访问网址、ua、ip等等。
- error_log:错误日志
5.2.4 一些web 服务器还具有API网关(api gateway)的能力
一个应用的表现形式有很多,比如手机端、网页端等等,但是服务只有一个。
5.2.5 一些web 服务器提供TLS终结能力
web 服务器的代表是 apache、nginx、caddy。
5.2.6 页面常见性能指标
- 是否显示? 首次绘制时间FP、首次内容绘制FCP
- 关键元素是否显示? 首次有效绘制FMP、主角元素计时
- 是否可用? 可交互时间TTI
- 是否卡顿? CPU消耗、输入延迟等
5.2.7 网络优化策略
缓存
- http缓存
- 移动端缓存(native)
- 服务端缓存(redis、ssr等)
压缩
- JS压缩、CSS压缩、HTML压缩
- uglifyjs/xxx minify
- GZIP
- express/nginx/caddy
- 合并
- 雪碧图
- 请求合并
- 离线包 (例如:在打开APP期间将资源推送到APP的缓存中)
- 预加载
- APP预加载完整容器(Webview)
- H5应用预加载下一个页面的数据
6. 复习与总结
1. HTTP,HTTP1.1,HTTP2.0做了哪些优化?
2. 为什么要三次握手四次挥手?
1. TCP 建立连接时,为什么是三次握手?
TCP 建立连接时,通过三次握手能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。
不使用「两次握手」和「四次握手」的原因:
- 「两次握手」:无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号;
- 「四次握手」:三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
2. 为什么 TCP 挥手需要四次呢?
服务器收到客户端的 FIN 报文时,内核会马上回一个 ACK 应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送 FIN 报文,而是将发送 FIN 报文的控制权交给服务端应用程序:
- 如果服务端应用程序有数据要发送的话,就发完数据后,才调用关闭连接的函数;
- 如果服务端应用程序没有数据要发送的话,可以直接调用关闭连接的函数,
从上面过程可知,是否要发送第三次挥手的控制权不在内核,而是在被动关闭方(上图的服务端)的应用程序,因为应用程序可能还有数据要发送,由应用程序决定什么时候调用关闭连接的函数,当调用了关闭连接的函数,内核就会发送 FIN 报文了,所以服务端的 ACK 和 FIN 一般都会分开发送。
3. 什么叫restful风格?
Restful是一种设计风格。对于我们Web开发人员来说。就是使用一个url地址表示一个唯一的资源。然后把原来的请求参数加入到请求资源地址中。然后原来请求的增,删,改,查操作。改为使用HTTP协议中请求方式GET、POST、PUT、DELETE表示。
把请求参数加入到请求的资源地址中 原来的增,删,改,查。使用HTTP请求方式,POST、DELETE、PUT、GET分别一一对应。
传统的请求接口方式/api/addNewGoods
restful风格的接口以资源命名,比如接口为goods
增加商品:post goods
修改商品:put goods
删除商品:delete goods
4. 浏览器资源缓存
- 强制缓存:就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。max-age
- 协商缓存:会请求服务器
5. 正向代理和反向代理
正向代理是客户端找代理,把自己的请求转发给服务端,比如vpn就是正向代理;
而反向代理,则是服务端找代理,把自己接受到的请求转发给背后的其他机器,比如nginx就是反向代理;
正向代理,代理服务器为客户端服务;反向代理,代理服务器为服务端服务。
6. 文件上传有哪些格式,有什么区别?
文件上传格式有form表单和js提交,
- 使用blob,也就是二进制内容提交,适合大文件提交
- base64提交,适合小文件提交