admin 管理员组文章数量: 887016
PDF.js是Mozilla提供支持的一个通用的、基于web标准的平台,用于解析和呈现PDF的插件。
有些时候文件太大时,需要有切片加载的功能,可以做以下配置,一般情况下是不需要更改什么的。
最关键的是需要让后端支持分片下载和头部字段返回
1. 第一步先检查响应头中是否出现Accept-Ranges: bytes (表明服务器支持分片加载)。
2.第二步检查响应头中是否出现 ‘Access-Control-Expose-Headers’:‘Accept-Ranges,Content-Range’ 是最关键的。因为往往很多后端程序员都忘记了加上这个响应头。而这直接导致了我们任何的设置都是不生效的,实现不了分片加载,因为浏览器默认只允许js读取以下七种如图所示的响应头。而Accept-Ranges头部字段默认是不允许被js读取的,未经过后端设置暴露Accept-Range字段,此时是不能通过js获取到该字段的值,即使这时候已经在浏览器开发工具中看到该接口的响应头中出现了此字段。
配置好后,此时我们应该看到响应头是这样的:
有些时候找了半天找不出原因,往往就是没有暴露头字段。导致没有获取到头字段。再比如导出表格时候需要获取到头字段content-dispositon(内容处置)中的文件名,如果此时后端没有设置==‘Access-Control-Expose-Headers’:‘content-disposition’==。前端通过js也是获取不到的,即使你在响应头字段中确切的看到它已经出现了,只是你获取不到而已。
PDF.js插件中切片配置相关属性如下:
##### 1 "disableAutoFetch": true, //是否禁用自动获取,true为禁用自动获取,开启分页
##### 2 "disableFontFace": false,
##### 3 "disableRange": false, //是否禁用range获取文件,false表示支持分页请求头
##### 4 "disableStream": true, //分页关键,是否禁用流的形式加载
1、URL输入不是ip时
查看缓存顺序:浏览器缓存-> 操作系统缓存->host(即本机的DNS解析)
2.http协议的核心部分
报文内容
3.http协议组成
HTTP 协议规定报文必须有 header,但可以没有 body,而 且在 header 之后必须要有一个“空行”,也就 是“CRLF”,十六进制的“0D0A”。
请求行加头部字段 = 请求头
状态行加头部字段 = 响应头
4.对 HTTP 报文的解析和处理实际上主要就是对头字段的处 理,理解了头字段也就理解了 HTTP 报文。
5.头部字段
HTTP/1.1 里唯一要求必须提供的头字段是 Host,它必 须出现在请求头里,标记虚拟主机名。
实体字段里要说的一个是Content-Length,它表示报文里 body 的长度,也就是请求头或响应头空行后面数据的长 度。服务器看到这个字段,就知道了后续有多少数据,可以 直接接收。如果没有这个字段,那么 body 就是不定长的, 需要使用 chunked 方式分段传输。
6.http方法
HTTP 协议里为什么要有“请求方法”这个东西呢? 这就要从 HTTP 协议设计时的定位说起了。还记得吗?蒂姆 ·伯纳斯 - 李最初设想的是要用 HTTP 协议构建一个超链接 文档系统,使用 URI 来定位这些文档,也就是资源。那么, 该怎么在协议里操作这些资源呢? 很显然,需要有某种“动作的指示”,告诉操作这些资源的 方式。所以,就这么出现了“请求方法”。它的实际含义就 是客户端发出了一个“动作指令”,要求服务器端对 URI 定 位的资源执行这个动作。 目前 HTTP/1.1 规定了八种方法,单词都必须是大写的形 式,我先简单地列把它们列出来,后面再详细讲解。 1. GET:获取资源,可以理解为读取或者下载数据; 2. HEAD:获取资源的元信息; 3. POST:向资源提交数据,相当于写入或上传数据; 4. PUT:类似 POST; 5. DELETE:删除资源; 6. CONNECT:建立特殊的连接隧道; 7. OPTIONS:列出可对资源实行的方法; 8. TRACE:追踪请求 - 响应的传输路径。
7.状态码
你发起了一个 GET 请求,想获取“/orders”这个文 件,但这个文件保密级别比较高,不是谁都能看的,服务器 就可以有如下的几种响应方式: 1. 假装这个文件不存在,直接返回一个 404 Not found 报 文; 2. 稍微友好一点,明确告诉你有这个文件,但不允许访问, 返回一个 403 Forbidden; 3. 再宽松一些,返回 405 Method Not Allowed,然后用 Allow 头告诉你可以用 HEAD 方法获取文件的元信息。
8、方法比较
八个标准请求方法
四个热门方法
head与get方法一样,使用场景:1.检查文件是否存在。2.检查文件是否有最新版本
post与put:post一般表示creat,put一般表示put
四个冷僻方法
delete
connect:要求服务器为客户端和另一台服务器建立连接隧道,原来服务器充当代理
options:列出可实行操作方法,在Allow字段返回
trace:显示传输路径,用户测试和诊断
其他方法:copy、lock、patch(打补丁)
安全方法:get、head
幂等(多次执行相同操作,结果也相同)方法:get、head、put(POST 理解成 INSERT,把 PUT 理解成 UPDATE,这样就 很清楚了。多次 INSERT 会添加多条记录,而多次 UPDATE 只操作一条记录,而且效果相同。)
9.URI(uniform resource identifier)包括URL(uniform resource locator)和URN
10.URI:
端口号有时可以省略,浏览器等客户端会依据 scheme 使用默认的端口号,例如 HTTP 的默认端口号是 80,HTTPS 的默认端口号是 443
PATH部分以/开始。比如file:///D:/http_study/www/中有三个/,第三个代表路径开始,因为省略了主机名
表示对资源附加额外的要求在 path 之后,用一个“?”开始,但不包含“?”
URI只能使用ASCII码,为可使用汉语、@&等引入编码机制(escape),转成十六进制字节值,前面加一个%
11.状态码
客户端可以依据代码适时转换 处理状态,例如继续发送请求、切换协议,重定向跳转等, 有那么点 TCP 状态转换的意思。
RFC标准把其分为五类,第一位表示分类,0-99不用。五类具体含义:
1××:提示信息,表示目前是协议处理的中间状态,还需 要后续的操作;
2××:成功,报文已经收到并被正确处理;
3××:重定向,资源位置发生变动,需要客户端重新发送请求;
4××:客户端错误,请求报文有误,服务器无法处理;
5××:服务器错误,服务器在处理请求时内部发生了错误。
1XX:我们偶尔能够见到的是“101 Switching Protocols”。它 的意思是客户端使用 Upgrade 头字段,要求在 HTTP 协议 的基础上改成其他的协议继续通信,比如 WebSocket。而 如果服务器也同意变更协议,就会发送状态码 101,但这之 后的数据传输就不会再使用 HTTP 了。
2××类状态码表示服务器收到并成功处理了客户端的请求, 这也是客户端最愿意看到的状态码。 “200 OK”是最常见的成功状态码,表示一切正常,服务 器如客户端所期望的那样返回了处理结果,如果是非 HEAD 请求,通常在响应头后都会有 body 数据。 “204 No Content”是另一个很常见的成功状态码,它的 含义与“200 OK”基本相同,但响应头后没有 body 数 据。所以对于 Web 服务器来说,正确地区分 200 和 204 是很必要的。 “206 Partial Content”是 HTTP 分块下载或断点续传的 基础,在客户端发送“范围请求”、要求获取资源的部分数 据时出现,它与 200 一样,也是服务器成功处理了请求, 但 body 里的数据不是资源的全部,而是其中的一部分。 状态码 206 通常还会伴随着头字段“Content-Range”, 表示响应报文里 body 数据的具体范围,供客户端确认,例 如“Content-Range: bytes 0-99/2000”,意思是此次获 取的是总计 2000 个字节的前 100 个字节。
3××类状态码表示客户端请求的资源发生了变动,客户端必 须用新的 URI 重新发送请求获取资源,也就是通常所说 的“重定向”,包括著名的 301、302 跳转。 “301 Moved Permanently”俗称“永久重定向”,含 义是此次请求的资源已经不存在了,需要改用改用新的 URI 再次访问。 与它类似的是“302 Found”,曾经的描述短语 是“Moved Temporarily”,俗称“临时重定向”,意思 是请求的资源还在,但需要暂时用另一个 URI 来访问。 301 和 302 都会在响应头里使用字段Location指明后续要 跳转的 URI,最终的效果很相似,浏览器都会重定向到新的 URI。两者的根本区别在于语义,一个是“永久”,一个 是“临时”,所以在场景、用法上差距很大。 比如,你的网站升级到了 HTTPS,原来的 HTTP 不打算用 了,这就是“永久”的,所以要配置 301 跳转,把所有的 HTTP 流量都切换到 HTTPS。 再比如,今天夜里网站后台要系统维护,服务暂时不可用, 这就属于“临时”的,可以配置成 302 跳转,把流量临时 切换到一个静态通知页面,浏览器看到这个 302 就知道这 只是暂时的情况,不会做缓存优化,第二天还会访问原来的 地址。 “304 Not Modified” 是一个比较有意思的状态码,它用 于 If-Modified-Since 等条件请求,表示资源未修改,用于 缓存控制(即返回304代表资源未修改,不需要缓存)。它不具有通常的跳转含义,但可以理解成“重定 向已到缓存的文件”(即“缓存重定向”)。
4××类状态码表示客户端发送的请求报文有误,服务器无法 处理,它就是真正的“错误码”含义了。 “400 Bad Request”是一个通用的错误码,表示请求报 文有错误,但具体是数据格式错误、缺少请求头还是 URI 超 长它没有明确说,只是一个笼统的错误,客户端看到 400 只会是“一头雾水”“不知所措”。所以,在开发 Web 应 用时应当尽量避免给客户端返回 400,而是要用其他更有明 确含义的状态码。 “403 Forbidden”实际上不是客户端的请求出错,而是 表示服务器禁止访问资源。原因可能多种多样,例如信息敏 感、法律禁止等,如果服务器友好一点,可以在 body 里详 细说明拒绝请求的原因,不过现实中通常都是直接给一 个“闭门羹”。 “404 Not Found”可能是我们最常看见也是最不愿意看 到的一个状态码,它的原意是资源在本服务器上未找到,所 以无法提供给客户端。但现在已经被“用滥了”,只要服务 器“不高兴”就可以给出个 404,而我们也无从得知后面到 底是真的未找到,还是有什么别的原因,某种程度上它比 403 还要令人讨厌。 4××里剩下的一些代码较明确地说明了错误的原因,都很好 理解,开发中常用的有: 5×× 405 Method Not Allowed:不允许使用某些方法操作资 源,例如不允许 POST 只能 GET; 406 Not Acceptable:资源无法满足客户端请求的条 件,例如请求中文但只有英文; 408 Request Timeout:请求超时,服务器等待了过长的 时间; 409 Conflict:多个请求发生了冲突,可以理解为多线程 并发时的竞态; 413 Request Entity Too Large:请求报文里的 body 太 大; 414 Request-URI Too Long:请求行里的 URI 太大; 429 Too Many Requests:客户端发送了太多的请求, 通常是由于服务器的限连策略; 431 Request Header Fields Too Large:请求头某个字 段或总体太大;
12.http协议的特点
可靠传输:HTTP 协议是基于 TCP/IP 的,而 TCP 本身是一个“可靠”的传 输协议,所以 HTTP 自然也就继承了这个特性。必须正确地理解“可靠”的含义,HTTP 并不能 100% 保证数据一定能够发送到 另一端,在网络繁忙、连接质量差等恶劣的环境下,也有可能收发失败。“可靠”只是向使 用者提供了一个“承诺”,会在下层用多种手段“尽量”保证数据的完整送达。
请求-应答:在浏览器 - 服务器的场景里,通常服务器都 是应答方,但如果将它用作代理连接后端服务器,那么它就可能同时扮演请求方和应答方的 角色。
无状态:“状态”其实就是客户端或者服务器里保存的一些数据或者标志,“无状态”形象地来说就是“没有记忆能力”。比如,浏览器发了一个请求,说“我是小 明,请给我 A 文件。”,服务器收到报文后就会检查一下权限,看小明确实可以访问 A 文 件,于是把文件发回给浏览器。接着浏览器还想要 B 文件,但服务器不会记录刚才的请求 状态,不知道第二个请求和第一个请求是同一个浏览器发来的,所以浏览器必须还得重复一 次自己的身份才行:“我是刚才的小明,请再给我 B 文件。” 我们可以再对比一下 UDP 协议,不过它是无连接也无状态的,顺序发包乱序收包,数据包 发出去后就不管了,收到后也不会顺序整理。而 HTTP 是有连接无状态,顺序发包顺序收 包,按照收发的顺序管理报文。
题外话:以前http是无连接,但是很影响性能,在http1.1就改成了总是默认启用keepalive长连接机制。所以现在的http已经不再是无连接了。
13.http的优点和缺点
1.优点
最重要也是最突出的优点是“简单、灵活、易于扩展”。“简单”蕴含了进化和扩展的可能性,“少即是多”。
应用广泛
2.双刃剑
无状态:减轻服务器负担,服务器没有状态差异,可以很容易地组成集群。(“无状态”也表示服务器都是相同的,没有“状态”的差异,所以可以很容易地组成 集群,让负载均衡把请求转发到任意一台服务器,不会因为状态不一致导致处理出错,使 用“堆机器”的“笨办法”轻松实现高并发高可用。)那么,“无状态”又有什么坏处呢? 既然服务器没有“记忆能力”,它就无法支持需要连续多个步骤的“事务”操作。例如电商 购物,首先要登录,然后添加购物车,再下单、结算、支付,这一系列操作都需要知道用户 的身份才行,但“无状态”服务器是不知道这些请求是相互关联的,每次都得问一遍身份信 息,麻烦且增加不必要的数据传输量。,HTTP 协议最好是既“无状态”又“有状态”,不过还真有“鱼和熊掌”两者兼得这 样的好事,这就是“小甜饼”Cookie 技术。
明文:好处:易于调试。坏处:不安全
3.缺点:
不安全:缺乏身份认证、完整性校验。解决办法:https
4.总方面:
性能:不算差、不够好。瓶颈:请求-应答通信模式。现在互联网特点:移动、高并发。请求-应答通信模式加剧http性能问题,即著名队头阻塞问题。
解决办法:WEB性能优化
官方:缓存
非官方:如切图、数据内嵌与 合并,域名分片
终极解决方案:http/2 http/3
14.格式
数据类型与编码
1.原因:因为http是 应用层协议,数据到达后工作只完成一半,要告诉诉上层应用这是什么数 据才行,否则上层应用不知所措。
2.HTTP截取了一部分MIME type(Multipurpose internet Mail extensions多 用途互联网邮件扩展).MIME 把数据分成了八大类,每个大类下再细分出多个子 类,形式是“type/subtype”的字符串
- text:即文本格式的可读数据,我们最熟悉的应该就是 text/html 了,表示超文本文档,此外还有纯文本 text/plain、样式表 text/css 等。
- image:即图像文件,有 image/gif、image/jpeg、 image/png 等。
- audio/video:音频和视频数据,例如 audio/mpeg、 video/mp4 等。
- application:数据格式不固定,可能是文本也可能是二 进制,必须由上层应用程序来解释。常见的有 application/json,application/javascript、 application/pdf 等,另外,如果实在是不知道数据是什 么类型,像刚才说的“黑盒”,就会是 application/octet-stream,即不透明的二进制数据。
2.语言类型与编码分隔 符不是“/”,而是“-”。
15.大文件传输
1.数据压缩,把大象压成小猪装进冰箱,50%压缩率代表网速提升一倍。
2.chunked分块传输
3.范围请求:(拖拽进度、断点续传),响应状态码为206:partial content
比如,你在看当下正热播的某穿越剧,想跳过片头,直接看 正片,或者有段剧情很无聊,想拖动进度条快进几分钟,这 实际上是想获取一个大文件其中的片段数据,而分块传输并 没有这个能力。
16.http连接管理
只要向服务器发送了第一次请求,后续的请求都会重 复利用第一次打开的 TCP 连接,也就是长连接,不过不管客户端是否显式要求长连接,如果服务器支持长连 接,它总会在响应报文里放一个“Connection: keepalive”字段,告诉客户端:“我是支持长连接的,接下来 就用这个 TCP 一直收发数据吧”。
短连接:3/5=60%时间在浪费。
17.队头阻塞
“队头阻塞”与短连接和长连接无关,而是由 HTTP 基本 的“请求 - 应答”模型所导致的。
因为“请求 - 应答”模型不能变,所以“队头阻塞”问题在 HTTP/1.1 里无法解决,只能缓解,
并发连接。公司里可以再多买几台打卡机放在前台,这样大家可以不用 挤在一个队伍里,分散打卡,一个队伍偶尔阻塞也不要紧, 可以改换到其他不阻塞的队伍。
域名分片(domain sharding)。公司发展的太快了,员工越来越多,上下班打卡成了迫在眉 睫的大问题。前台空间有限,放不下更多的打卡机了,怎么 办?那就多开几个打卡的地方,每个楼层、办公区的入口也 放上三四台打卡机,把人进一步分流,不要都往前台挤。HTTP 协议和浏览器不是限制并发连接数量吗?好,那我就 多开几个域名,比如 shard1.chrono、 shard2.chrono,而这些域名都指向同一台服务器 www.chrono,这样实际长连接的数量就又上去了, 真是“美滋滋”。不过实在是有点“上有政策,下有对 策”的味道。
18.http的重定向和跳转
跳转动作:
主动跳转
被动跳转:重定向
重定向原因:
301永久重定向:资源不可用、避免重复(多个网址都跳转到一个 URI,增加访问入口的同时还不会增加额外的工作量。)
301临时重定向:系统维护,把网站重定向到一个通知页面,告诉用 户过一会儿再来访问。另一种用法就是“服务降级”,比如 在双十一促销的时候,把订单查询、领积分等不重要的功能 入口暂时关闭,保证核心服务能够正常运行。
响应头字段 Location 指示了要跳转的 URI,可以用绝对 或相对的形式;
使用重定向时需要当心性能损耗(因为相当于两次请求),还要避免出现循环跳转。
重定向是服务器发起的跳转,要求客户端改用新的 URI 重新发送请求,通常会自动进行,用户是无感知的;
19.HTTP的Cookie机制
无状态:即使这个请求会让服 务器发生 500 的严重错误,下次来也会依旧“热情招待”。
现状:随着 HTTP 应用领域的不断扩大,对“记忆能力”的需求也越来越强 烈。比如网上论坛、电商购物,都需要“看客下菜”,只有记住用户的身份才能执行发帖 子、下订单等一系列会话事务。
机制:服务器委托浏览器存储信息在浏览器
Cookie属性:
Expires”俗称“过期时间”,是绝对时间点。“Max-Age”用的是相对时间。优先使用Max-Age
“Domain”和“Path”指定了 Cookie 所属的域名和路径,浏 览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果 不满足条件,就不会在请求头里发送 Cookie。
Cookie 的安全性:写过前端的同学一定知道,在 JS 脚本里可以用 document.cookie 来读写 Cookie 数据, 这就带来了安全隐患,有可能会导致“跨站脚本”(XSS)攻击窃取数据。 属性“HttpOnly”会告诉浏览器,此 Cookie 只能通过浏览器 HTTP 协议传输,禁止其他 方式访问,浏览器的 JS 引擎就会禁用 document.cookie 等一切相关的 API,脚本攻击也 就无从谈起了。 另一个属性“SameSite”可以防范“跨站请求伪造”(XSRF)攻击,设置 成“SameSite=Strict”可以严格限定 Cookie 不能随着跳转链接跨站发送, 而“SameSite=Lax”则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发 送。
cookie应用:
身份识别
是广告跟踪。 你上网的时候肯定看过很多的广告图片,这些图片背后都是广告商网站(例如 Google), 它会“偷偷地”给你贴上 Cookie 小纸条,这样你上其他的网站,别的广告就能用 Cookie 读出你的身份,然后做行为分析,再推给你广告。
总结:
为了保护 Cookie,还要给它设置有效期、作用域等属性,常用的有 Max-Age、 Expires、Domain、HttpOnly 等;
,因为 Cookie 并不属于 HTTP 标准(RFC6265,而不是 RFC2616/7230),所以语法上与其他字段不太一致,使用的分隔符是“;”,与 Accept 等字段的“,”不同,小心不要弄错了。
不指定过期时间,浏览器关闭时失效,即session cookie
20.HTTP的缓存控制
原因:由于链路漫长,网络时延不可控,浏览器使用 HTTP 获取资源的成本较高。所以,非常有 必要把“来之不易”的数据缓存起来,下次再请求的时候尽可能地复用。这样,就可以避免 多次请求 - 应答的通信成本,节约网络带宽,也可以加快响应速度。
服务器缓存控制:服务器标记资源有效期使用的头字段是“Cache-Control”,里面的值“maxage=30”就是资源的有效时间,单位为s。“max-age”是 HTTP 缓存控制最常用的属性,此外在响应报文里还可以用其他的属性来 更精确地指示浏览器应该如何使用缓存:no_store:不允许缓存,用于某些变化非常频繁的数据,例如秒杀页面; no_cache:它的字面含义容易与 no_store 搞混,实际的意思并不是不允许缓存,而是 可以缓存,但在使用之前必须要去服务器验证是否过期,是否有最新的版本;
3.客户端的缓存控制:浏览器也可以发“Cache-Control”,也就 是说请求 - 应答的双方都可以用这个字段进行缓存控制,互相协商缓存的使用策略。
4.条件请求:
条件请求一共有 5 个头字段,我们最常用的是“if-Modified-Since”和“If-NoneMatch”这两个。 需要第一次的响应报文预先提供“Last-modified”和“ETag”,然后 第二次请求时就可以带上缓存里的原值,验证资源是否是最新的。
如果资源没有变,服务器就回应一个“304 Not Modified”,表示缓存依然有效,浏览器 就可以更新一下有效期,然后放心大胆地使用缓存了。
ETag 是“实体标签”(Entity Tag)的缩写,是资源的一个唯一标识,就可以精确地识别资源的变动情况。比如能精确区分一秒内改变好多次,监测出只改变顺序或空格。
5.cache和cookie的异同点
不同点:cookie会发送到服务器,cache不会
21.HTTP的代理服务
定义:代理服务”就是指服务本身不生产内容,而是处于中间位置转发上下游的请求和响 应,具有双重身份:
分类:正向代理、反向代理
反向代理:功能:负载均衡
负载均衡因为在面向客户端时屏蔽了源服务器,客户端看到的只 是代理服务器,源服务器究竟有多少台、是哪些 IP 地址都不知道。于是代理服务器就可以 掌握请求分发的“大权”,决定由后面的哪台服务器来响应请求
安全防护:保护被代理的后端服务器,限制 IP 地址或流量,抵御网络攻击和过载;
数据过滤
22.HTTP的缓存代理。空间换时间思想
“缓存代理”,也就是支持缓存控制的代理服务。
原因:HTTP 传输链路上,不只是客户端有缓存,服务器上的缓存也是非常有价值的,可以让 请求不必走完整个后续处理流程,“就近”获得响应结果。
背景:特别是对于那些“读多写少”的数据,例如突发热点新闻、爆款商品的详情页,一秒钟内可 能有成千上万次的请求。即使仅仅缓存数秒钟,也能够把巨大的访问流量挡在外面,让 下载APP RPS(request per second)降低好几个数量级,减轻应用服务器的并发压力,对性能的 改善是非常显著的。
我们要区分客户端上的缓存和代理上的缓存,可以使用两个新属 性“private”和“public”。
Vary:它是内容协商的结果,相当于报文的一个 版本标记。 同一个请求,经过内容协商后可能会有不同的字符集、编码、浏览器等版本。比 如,“Vary: Accept-Encoding”“Vary: User-Agent”,缓存代理必须要存储这些不同 的版本。 当再收到相同的请求时,代理就读取缓存里的“Vary”,对比请求头里相应的“ AcceptEncoding”“User-Agent”等字段,如果和上一个请求的完全匹配,比如都 是“gzip”“Chrome”,就表示版本一致,可以返回缓存的数据。
23.HTTPS是什么?SSL/TLS又是什么?
原因:http不安全(比如,前几讲中说过的“代理服务”。它作为 HTTP 通信的中间人,在数据上下行的时候 可以添加或删除部分头字段,也可以使用黑白名单过滤 body 里的关键字,甚至直接发送 虚假的请求、响应,而浏览器和源服务器都没有办法判断报文的真伪。)
HTTPS:规定了新 的协议名“https”,默认端口号 443.其他都一样,缺点少了明文和不安全。
3.TLS:
TLS 由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成, 综合使用了对称加密、非对称加密、身份认证等许多密码学前沿技术。
浏览器和服务器在使用 TLS 建立连接时需要选择一组恰当的加密算法来实现安全通信,这 些算法的组合被称为“密码套件”(cipher suite,也叫加密套件)。
比如ECDHE-RSA-AES256-GCM-SHA384:基本的形式是“密钥交换算法 + 签名算法 + 对称加密算法 + 摘要算法”,比如刚才的密码 套件的意思就是: “握手时使用 ECDHE 算法进行密钥交换,用 RSA 签名和身份认证,握手后的通信使用 AES 对称算法,密钥长度 256 位,分组模式是 GCM,摘要算法 SHA384 用于消息认证和 产生随机数。”
3.OpenSSL:说到 TLS,就不能不谈到 OpenSSL,它是一个著名的开源密码学程序库和工具包,几乎支 持所有公开的加密算法和协议,已经成为了事实上的标准,许多应用软件都会使用它作为底 层库来实现 TLS 功能,包括常用的 Web 服务器 Apache、Nginx 等。
4.什么是安全:
机密性,完整性,身份认证,不可否认。
机密性实现:加密。完整性:接口签名。身份认证:数字签名。
24.对称加密与非对称加密
1.密钥:单位是“位”(bit),而不是“字节”(byte)。比如,说密钥长度是 128,就是 16 字节的二进制串
2.加密类型:按照密钥的使用方式,加密可以分为两大类:对称加密和非对称加密。
对称加密算法:常用的只有 AES(应用最广泛的对称加密算法。) 和 ChaCha20。缺点:密钥交换会泄露
非对称加密算法(公钥加密算法):它有两个密钥,一个叫“公钥”(public key),一个叫“私钥”(private key)。单向性:公钥加密后只能用私钥解 密,反过来,私钥加密后也只能用公钥解密。解决问题:密钥交换。(非对称加密可以解决“密钥交换”的问题。网站秘密保管私钥,在网上任意分发公钥,你想 要登录网站只要用公钥加密就行了,)缺点:低效。
RSA:非对称加密算法的设计要比对称算法难得多。TLS 里只有很少的几种,最著名的是RSA。后起之秀:ECC
3.实际运用:看到这里,你是不是认为可以抛弃对称加密,只用非对称加密来实现机密性呢? 很遗憾,虽然非对称加密没有“密钥交换”的问题,但因为它们都是基于复杂的数学难题, 运算速度很慢,即使是 ECC 也要比 AES 差上好几个数量级。如果仅用非对称加密,虽然保 证了安全,但通信速度有如乌龟、蜗牛,实用性就变成了零。
混合加密:在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE,首先解决密钥交换的问题。 然后用随机数产生对称算法使用的“会话密钥”(session key),再用公钥加密。因为会 话密钥很短,通常只有 16 字节或 32 字节,所以慢一点也无所谓。 对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换,后 续就不再使用非对称加密,全都使用对称加密。
把对称加密和非对称加密结合起来就得到了“又安全又快”的混合加密,也就是 TLS 里使 用的加密方式。
4.公钥解私钥有什么用?
. 在混合加密中用到了公钥加密,因为只能由私钥解密。那么反过来,私钥加密后任何人 都可以用公钥解密,这有什么用呢?
私钥加密用公钥解是为了做身份认证,不可抵赖,因为默认私钥只有持有人知道
25.数字签名与证书
1.只有机密性坏处:
收集多次密文,根据服务器反应推出明文。
2.完整性解决:摘要算法(Digest Algorithm)、原文附摘要
也就是常说的散列函数、哈希 函数(Hash Function)。
最常用的两个摘要算法:MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1):能够生成 16 字节和 20 字节长度 的数字摘要。但这两个算法的安全强度比较低,不够安全,在 TLS 里已经被禁止使用了。
目前 TLS 推荐使用的是 SHA-1 的后继者:SHA-2。SHA-2 实际上是一系列摘要算法的统称,总共有 6 种,常用的有 SHA224、SHA256、 SHA384,分别能够生成 28 字节、32 字节、48 字节的摘要。
原文附摘要,就能够保证数据的完整性。比如,你发了条消息:“转账 1000 元”,然后再加上一个 SHA-2 的摘要。网站收到后也 计算一下消息的摘要,把这两份“指纹”做个对比,如果一致,就说明消息是完整可信的, 没有被修改。
3.“身份认证”和“不可否认解决:公钥解密私钥(私钥加密的是原文的摘要)
原因:黑客可以伪装成网站来窃取信息。而反过来,他也可以伪装成你,向网 站发送支付、转账等消息,网站没有办法确认你的身份,钱可能就这么被偷走了。
但又因为非对称加密效率太低,所以私钥只加密原文的摘要,这样运算量就小的多,而且得 到的数字签名也很小,方便保管和传输。
原理:刚才的这两个行为也有专用术语,叫做“签名”和“验签”。 只要你和网站互相交换公钥,就可以用“签名”和“验签”来确认消息的真实性,因为私钥 保密,黑客不能伪造签名,就能够保证通信双方的身份。如下:
4.公钥的信任解决:数字证书
1.背景:到现在,综合使用对称加密、非对称加密和摘要算法,我们已经实现了安全的四大特性,是 不是已经完美了呢? 不是的,这里还有一个“公钥的信任”问题。因为谁都可以发布公钥,我们还缺少防止黑客 伪造公钥的手段,也就是说,怎么来判断这个公钥就是你或者某宝的公钥呢? 真是“按下葫芦又起了瓢”,安全还真是个麻烦事啊,“一环套一环”的。 我们可以用类似密钥交换的方法来解决公钥认证问题,用别的私钥来给公钥签名,显然,这 又会陷入“无穷递归”。 但这次实在是“没招”了,要终结这个“死循环”,就必须引入“外力”,找一个公认的可 信第三方,让它作为“信任的起点,递归的终点”,构建起公钥的信任链。
2.数字证书:颁发的东西+签名=数字证书
3.知名的 CA 全世界就那么几家,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等, 它们签发的证书分 DV、OV、EV 三种,区别在于可信程度。DV 是最低的,只是域名级别的可信,背后是谁不知道。EV 是最高的,经过了法律和审计 的严格核查,可以证明网站拥有者的身份(在浏览器地址栏会显示出公司的名字,例如 Apple、GitHub 的网站)。以下是vue源码社区官网的证书路径。
4.证书体系的弱点 证书体系(PKI,Public Key Infrastructure)虽然是目前整个网络世界的安全基础设施, 但绝对的安全是不存在的,它也有弱点,还是关键的“信任”二字。 如果 CA 失误或者被欺骗,签发了错误的证书,虽然证书是真的,可它代表的网站却是假 的。 还有一种更危险的情况,CA 被黑客攻陷,或者 CA 有恶意,因为它(即根证书)是信任的 源头,整个信任链里的所有证书也就都不可信了。 这两种事情并不是“耸人听闻”,都曾经实际出现过。所以,需要再给证书体系打上一些补 丁。 针对第一种,开发出了 CRL(证书吊销列表,Certificate revocation list)和 OCSP(在线 证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书。 对于第二种,因为涉及的证书太多,就只能操作系统或者浏览器从根上“下狠手”了,撤销 对 CA 的信任,列入“黑名单”,这样它颁发的所有证书就都会被认为是不安全的。
5.总结:
摘要算法用来实现完整性,能够为数据生成独一无二的“指纹”,常用的算法是 SHA2;
数字签名是私钥对摘要的加密,可以由公钥解密后验证,实现身份认证和不可否认;
公钥的分发需要使用数字证书,必须由 CA 的信任链来验证,否则就是不可信的;
作为信任链的源头 CA 有时也会不可信,解决办法有 CRL、OCSP,还有终止信任。
26.信任始于握手:TLS1.2连接过程解析
1.在浏览器地址栏里键入“https”开头的 URI,再按下回车,会发生什么呢
提出协议名和域名。得出端口号和ip地址。启用tcp连接。
2.http与https连接过程对比:
在 HTTP 协议里,建立连接后,浏览器会立即发送请求报文。但现在是 HTTPS 协议,它需 要再用另外一个“握手”过程,在 TCP 上建立安全连接,之后才是收发 HTTP 报文。
3.TLS 的握手过程
今天我们学习了 HTTPS/TLS 的握手,内容比较多、比较难,不过记住下面四点就可以。
- HTTPS 协议会先与服务器执行 TCP 握手,然后执行 TLS 握手,才能建立安全连接;
- “Change Cipher Spec”之前传输的都是明文,之后都是对称密钥加密的密文。
27.HTTP两个缺点解决:
1.安全性解决:HTTPS
2.性能低效解决:HTTP/2
28.HTTP/2
1.原因:引入 SSL/TLS后安全达到极致,性能改善只能依赖于“长连接”这种“落后”的技术。
2.对比HTTP/1改动:
因为必须要保持功能上的兼容,所以 HTTP/2 把 HTTP 分解成了“语义”和“语法”两个 部分,“语义”层不做改动,与 HTTP/1 完全一致(即 RFC7231)。比如请求方法、 URI、状态码、头字段等概念都保留不变。
在“语义”保持稳定之后,HTTP/2 在“语法”层做了“天翻地覆”的改造,完全变更了 HTTP 报文的传输格式
3.优化手段:
1.数据冗余和头大身小解决:头部压缩:客户端 和服务器两端建立“字典”,用索引号表示重复的字符串。釆用哈夫曼编码来压缩整数和 字符串
原因:头部字段多、响应字段里面很多重复字段。(报文 Header 一般会携带“User Agent”“Cookie”“Accept”“Server”等许多 固定的头字段,多达几百字节甚至上千字节,但 Body 却经常只有几十字节(比如 GET 请 求、204/301/304 响应),成了不折不扣的“大头儿子”。)
语义上它与 HTTP/1 兼容,所以报文还是由“Header+Body”构成的,但在请求发送 前,必须要用“HPACK”算法来压缩头部数据。
2.队头阻塞解决:二进制格式:报文HTTP/1 里纯文本——>HTTP/2里二进制“帧”。
把原来的“Header+Body”的消息“打散”为 数个小片的二进制“帧”(Frame),用“HEADERS”帧存放头数据、“DATA”帧存放 实体数据。
在“流”的层面上看,消息是一些有序的“帧”序列,而在“连接”的层面上看,消息却是 乱序收发的“帧”。多个请求 / 响应之间没有了顺序关系,不需要排队等待,也就不会再 出现“队头阻塞”问题,降低了延迟,大幅度提高了连接的利用率。
4.对比HTTP/1不同
1.头部压缩:HTTP/2 使用“HPACK”算法压缩头部信息,消除冗余数据节约带宽;
2.报文传输改动:HTTP/2 使用二进制流传输消息,解决了困扰多年的“队头阻塞”问题。
3.多路复用:又因为流可以并发,所以 HTTP/2 就可以实 现无阻塞的多路复用。
从上图可知,可以并发流数据,服务器再异步接收
3.可以服务器 推送:在浏览器刚请求 HTML 的时 候就提前把可能会用到的 JS、CSS 文件发给客户端,减少等待的延迟,这被称为“服务器 推送”(Server Push,也叫 Cache Push)。
4.强化安全:要求至少是 TLS1.2,而且禁用了很多不安全的密码套件
下面的这张图对比了 HTTP/1、HTTPS 和 HTTP/2 的协议栈,你可以清晰地看到,HTTP/2 是建立在“HPack”“Stream”“TLS1.2”基础之上的,比 HTTP/1、HTTPS 复杂了一 些。
5.总结:
HPACK”算法是一个“有状态”的算法,需要客户端和服务器各自维护一份“索引表”,也可以说是“字 典”(这有点类似 brotli),压缩和解压缩就是查表和更新表的操作。
HTTP/2 把报文切分为多种类型的二进制帧,报头里最重要的字段是流标识符,标记帧 属于哪个流;
在一个 HTTP/2 连接上可以并发多个流,也就是多个“请求 - 响应”报文,这就是“多 路复用”。
http/2的头字段必须完全小写。Http/1中不区分大小写
5.
6.对HTTP/2的一句话总结:头部压缩、二进制分帧、虚拟的“流”与多路复用,性能方面比 HTTP/1 有了很大的提 升,“基本上”解决了“队头阻塞”这个“老大难”问题。
29.HTTP/3
1.为什么HTTP/2说是“基本上”,而不是“完全”解决了队头阻塞呢?
答:在网络良好的情况下,包可以很快送达目的地。但如果网络质量比较差,像手机上网的时 候,就有可能会丢包。而 TCP 为了保证可靠传输,有个特别的“丢包重传”机制,丢失的 包必须要等待重新传输确认,其他的包即使已经收到了,也只能放在缓冲区里,上层的应用 拿不出来,只能“干着急”。 我举个简单的例子: 客户端用 TCP 发送了三个包,但服务器所在的操作系统只收到了后两个包,第一个包丢 了。那么内核里的 TCP 协议栈就只能把已经收到的包暂存起来,“停下”等着客户端重传 那个丢失的包,这样就又出现了“队头阻塞”。 由于这种“队头阻塞”是 TCP 协议固有的,所以 HTTP/2 即使设计出再多的“花样”也无 法解决。
一句话概括:tcp丢包重传机制使HTTP/2无法完全解决队头阻塞。它只解决了要等上一个包传输完才可传输原因导致的队头阻塞问题。
2.QUIC不会重连:
比如你下班回家,手机会自动由 4G 切换到 WiFi。这时 IP 地址会发生变化,TCP 就必须重 新建立连接。而 QUIC 连接里的两端连接 ID 不会变,所以连接在“逻辑上”没有中断,它 就可以在新的 IP 地址上继续使用之前的连接,消除重连的成本,实现连接的无缝迁移。
3.HTTP/3总结:
HTTP/3 基于 QUIC 协议,完全解决了“队头阻塞”问题,弱网环境下的表现会优于 HTTP/2; 2. QUIC 是一个新的传输层协议,建立在 UDP 之上,实现了可靠传输;
3. QUIC 内含了 TLS1.3,只能加密通信,支持 0-RTT 快速建连;
4. QUIC 的连接使用“不透明”的连接 ID,不绑定在“IP 地址 + 端口”上,支持“连接 迁移”;
5.HTTP/3 没有指定默认端口号,需要用 HTTP/2 的扩展帧“Alt-Svc”来发现。
30.HTTP/2与HTTP/1比较:
1.HTTP/2不使用精灵图和域名分片的原因:
因为HTTP/2中使用小颗粒化的资源,优化了缓存,而使用精灵图就相当于传输大文件, 但是大文件会延迟客户端的处理执行,并且缓存失效的开销很昂贵,很少数量的数据更新 就会使整个精灵图失效,需要重新下载(http1中使用精灵图是为了减少请求);
2.HTTP/2优缺点:
优点:头部压缩,节省带宽。二进制流传输,多路复用,高效传输且部分解决队头阻塞问题;服务器推送,降低延迟。(它不需要客户端预先请求,服务器直接就发给客 户端,这就省去了客户端解析 HTML 再请求的时间。比如请求html时把所需css和js发送过去)
缺点:没有全部解决队头阻塞问题;对一个域名只开一个连接,所以一旦这个连接出问题,那么整个网站 的体验也就变差了。
31.Nginx:
1.我画了一张 Nginx“I/O 多路复用”的示意图,你可以看到,它的形式与 HTTP/2 的 流非常相似,每个请求处理单独来看是分散、阻塞的,但因为都复用到了一个线程里,所以 资源的利用率非常高。
2.采用的是进程池+单进程机制。
3.Nginx 依赖于磁盘上的静态配置文件,修改后必须重启才能生效,缺乏灵活性;
32.HTTP攻击
1.跨站脚本”(XSS)攻击:
js调用API获取cookie
输入js获取数据库信息
33.CDN
1.为什么要用到CDN
互联网从逻辑上看是一张大网,但实际上是由许多小网络组成的,这其中 就有小网络“互连互通”的问题,典型的就是各个电信运营商的网络,比如国内的电信、联 通、移动三大家。 这些小网络内部的沟通很顺畅,但网络之间却只有很少的联通点。如果你在 A 网络,而网 站在 C 网络,那么就必须“跨网”传输,和成千上万的其他用户一起去“挤”连接点 的“独木桥”。而带宽终究是有限的,能抢到多少只能看你的运气。 还有,网络中还存在许多的路由器、网关,数据每经过一个节点,都要停顿一下,在二层、 三层解析转发,这也会消耗一定的时间,带来延迟。 把这些因素再放到全球来看,地理距离、运营商网络、路由转发的影响就会成倍增加。想象 一下,你在北京,访问旧金山的网站,要跨越半个地球,中间会有多少环节,会增加多少时延?
这个时候 CDN 就出现了,它就是专门为解决“长距离”上网络访问速度慢而诞生的一种网络应用服务。
2.CDN原理
CDN 构建了全国、全球级别的专网,让用户就近访问专网里的边缘节点,降低了传输 延迟,实现了网站加速;
GSLB 是 CDN 的“大脑”,使用 DNS 负载均衡技术,智能调度边缘节点提供服务;
缓存系统是 CDN 的“心脏”,使用 HTTP 缓存代理技术,缓存命中就返回给用户,否 则就要回源。
3.CDN是怎么运行的?
它有两个关键组成部分:全局负载均衡和缓存系 统
全局负载均衡(Global Sever Load Balance)一般简称为 GSLB,它是 CDN 的“大 脑”,主要的职责是当用户接入网络的时候在 CDN 专网中挑选出一个“最佳”节点提供服 务,解决的是用户如何找到“最近的”边缘节点,对整个 CDN 网络进行“负载均衡”。GSLB 最常见的实现方式是“DNS 负载均衡”。
原来没有 CDN 的时候,权威 DNS 返回的是网站自己服务器的实际 IP 地址,浏览器收到 DNS 解析结果后直连网站。
但加入 CDN 后就不一样了,权威 DNS 返回的不是 IP 地址,而是一个 CNAME( Canonical Name ) 别名记录,指向的就是 CDN 的 GSLB。因为没拿到 IP 地址,于是本地 DNS 就会向 GSLB 再发起请求,这样就进入了 CDN 的全 局负载均衡系统,开始“智能调度”,主要的依据有这么几个:
- 看用户的 IP 地址,查表得知地理位置,找相对最近的边缘节点;
- 看用户所在的运营商网络,找相同网络的边缘节点;
- 检查边缘节点的负载情况,找负载较轻的节点;
- 其他,比如节点的“健康状况”、服务能力、带宽、响应时间等。
GSLB 把这些因素综合起来,用一个复杂的算法,最后找出一台“最合适”的边缘节点,把 这个节点的 IP 地址返回给用户,用户就可以“就近”访问 CDN 的缓存代理了。
2.CDN缓存代理
缓存系统是 CDN 的另一个关键组成部分,相当于 CDN 的“心脏”。这里就有两个 CDN 的关键概念:“命中”和“回源”。 “命中”就是指用户访问的资源恰好在缓存系统里,可以直接返回给用户;“回源”则正相 反,缓存里没有,必须用代理的方式回源站取。
3.网站也可以自建同城、异地多处机房,构建集群来提高服务能力,为什么非要选择 CDN 呢?
.自建成本太高,一般的公司玩不起
34.websocket
1、websocket是什么?产生原因?
“TCP Socket”,它实际上是一种功能接口, 通过这些接口就可以使用 TCP/IP 协议栈在传输层收发数据。“WebSocket”就是运行在“Web”,也就是 HTTP 上的 Socket 通信规范,提供与“TCP Socket”类似的功能,使用它就可以像“TCP Socket”一样调用下层协议栈,任意地收发数据。更准确地说,“WebSocket”是一种基于 TCP 的轻量级网络通信协议,在地位上是与 HTTP“平级”的。其实 WebSocket 与 HTTP/2 一样,都是为了解决 HTTP 某方面的缺陷而诞生的。HTTP/2 针对的是“队头阻塞”,而 WebSocket 针对的是“请求 - 应答”通信模式。
请求-应答模式的缺点:1.同一时刻只能 一个方向上有动作;2.只能是“被动”通信模式。
虽然后来的 HTTP/2、HTTP/3 新增了 Stream、Server Push 等特性,但“请求 - 应 答”依然是主要的工作方式。这就导致 HTTP 难以应用在动态页面、即时消息、网络游戏 等要求“实时通信”的领域。
在 WebSocket 出现之前,在浏览器环境里用 JavaScript 开发实时 Web 应用很麻烦。因 为浏览器是一个“受限的沙盒”,不能用 TCP,只有 HTTP 协议可用,所以就出现了很 多“变通”的技术,“轮询”(polling)就是比较常用的的一种。
2.WebSocket 的特点
WebSocket 的默认端口也选择了 80 和 443,因为现在互联网上的防火墙屏蔽了绝大多数 的端口,只对 HTTP 的 80、443 端口“放行”,所以 WebSocket 就可以“伪装”成 HTTP 协议,比较容易地“穿透”防火墙,与服务器建立连接。
WebSocket 利用 HTTP 协议实现连接握手,发送 GET 请求要求“协议升级”。WebSocket 的握手是一个标准的 HTTP GET 请求,但要带上两个协议升级的专用头字 段:
“Connection: Upgrade”,表示要求协议“升级”;
“Upgrade: websocket”,表示要“升级”成 WebSocket 协议。
35.性能优化
性能优化是一个复杂的概念,在 HTTP 里可以分解为服务器性能优化、客户端性能优化 和传输链路优化;
服务器有三个主要的性能指标:吞吐量、并发数和响应时间,此外还需要考虑资源利用 率;
客户端的基本性能指标是延迟,影响因素有地理距离、带宽、DNS 查询、TCP 握手 等
从服务器到客户端的传输链路可以分为三个部分,我们能够优化的是前两个部分,也就 是“第一公里”和“中间一公里”;
点击某个 URI,在 Timing 页里会显示出一个小型的“瀑布图”,是这个资源消耗时间的详 细分解,延迟的原因都列的清清楚楚,比如下面的这张图:
因为有“队头阻塞”,浏览器对每个域名最多开 6 个并发连接(HTTP/1.1),当页面里 链接很多的时候就必须排队等待(Queued、Queueing),这里它就等待了 1.62 秒, 然后才被浏览器正式处理; 浏览器要预先分配资源,调度连接,花费了 11.56 毫秒(Stalled); 连接前必须要解析域名,这里因为有本地缓存,所以只消耗了 0.41 毫秒(DNS Lookup); 与网站服务器建立连接的成本很高,总共花费了 270.87 毫秒,其中有 134.89 毫秒用于 TLS 握手,那么 TCP 握手的时间就是 135.98 毫秒(Initial connection、SSL); 实际发送数据非常快,只用了 0.11 毫秒(Request sent); 之后就是等待服务器的响应,专有名词叫 TTFB(Time To First Byte),也就是“首字 节响应时间”,里面包括了服务器的处理时间和网络传输时间,花了 124.2 毫秒; 从这张图你可以看到,一次 HTTP“请求 - 响应”的过程中延迟的时间是非常惊人的,总时 间 415.04 毫秒里占了差不多 99%。
6.TCP新特性:“TCP Fast Open”(Win10、 iOS9、Linux 4.1),它的效果类似 TLS 的“False Start”,可以在初次握手的时候就传输 数据,也就是 0-RTT,所以我们应该尽可能在操作系统和 Nginx 里开启这个特性
7.使用 domain 和 path 属性限定 Cookie 的作用域,尽可能减少 Cookie 的传输。
8.重定向引发的客户端延迟也很高,它不仅增加了一次请求往返,还有可能导致新域名的 DNS 解析,是 HTTP 前端性能优化的“大忌”。除非必要,应当尽量不使用重定向,或者 使用 Web 服务器的“内部重定向”。
9.不过你要注意,一些在 HTTP/1 里的优化手段到了 HTTP/2 里会有“反效果”。 对于 HTTP/2 来说,一个域名使用一个 TCP 连接才能够获得最佳性能,如果开多个域名, 就会浪费带宽和服务器资源,也会降低 HTTP/2 的效率,所以“域名收缩”在 HTTP/2 里 是必须要做的。 “资源合并”在 HTTP/1 里减少了多次请求的成本,但在 HTTP/2 里因为有头部压缩和多 路复用,传输小文件的成本很低,所以合并就失去了意义。而且“资源合并”还有一个缺 点,就是降低了缓存的可用性,只要一个小文件更新,整个缓存就完全失效,必须重新下 载。 所以在现在的大带宽和 CDN 应用场景下,应当尽量少用资源合并(JS、CSS 图片合并,数 据内嵌)。
版权声明:本文标题:PDF.js实现分片加载问题 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729002763h1305590.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论