图解http

本文详细介绍了HTTP协议,包括其诞生、工作原理、主要特点如无状态性、持久连接、内容编码、范围请求等,以及与之密切相关的TCP/IP、DNS、Cookie等技术。文章深入浅出地讲解了HTTP报文的结构、请求方法、状态码,以及各种首部字段的作用,还涉及了HTTPS协议确保Web安全的重要性。

第一章——了解web及网络基础

1.1 使用HTTP协议访问Web

在浏览器的地址栏输入URL时,可以看到web页面,即使你不了解其运作原理,也能看到web页面。

 发送请求获取服务器资源的web浏览器,称之为客户端。

 web使用一种名为HTTP(超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。

1.2 HTTP的诞生

1.2.1 为知识共享而规划web

WWW: 万维网world wide web

HTML:超文本标记语言hypertext markup language

URL :统一资源定位符uniform resource locator 

SGML:标准通用标记语言 standard generalized markup language

1.2.2 web 成长时代

1.2.3 驻足不前的HTTP

HTTP/0.9   HTTP/1.0  HTTP/1.1

1.3 网络基础TCP/IP

1.3.1 TCP/IP协议族

协议(Protocol):不同的硬件,操作系统之间的通信,所用的这一切都需要一种规则,这种规则称为协议。

 与互联网相关联的协议集合起来总称为TCP/IP。

1.3.2 TCP/IP的分层管理

TCP/IP协议族里最重要的一点就是分层。

TCP/IP分为四层:应用层、传输层、网络层、数据链路层

应用层:向用户提供应用服务时通信的活动。

HTTP协议就在这一层。

传输层:提供处于网络连接中的两台计算机之间的数据传输。

这一层的协议有: TCP(Transmission Control Protocol,传输控制协议)、UDP(User Data Protocol,用户数据报协议),DNS(Domain name system域名系统)

网络层:IP协议在这一层。

用来处理在网络层上流动的数据包。数据包是网络传输的最小数据单位。

数据链路层:用来处理网络的硬件部分。物理设备

1.3.3 ——TCP/IP通信传输流

 利用TCP/IP进行网络通信时,会通过分层顺序与对方进行通信。

发送端(客户端):从应用层往下走,

接收端(服务器):从应用层往上走。

接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的HTTP请求。

 封装:把数据信息包装起来的做法称为封装

1.4 与HTTP关系密切的协议:IP、 TCP和DNS

1.4.1 负责传输的IP协议

IP位于网络层,所有使用网络的系统都会用到IP协议。

IP和IP地址:
IP其实是一种协议的名称。

IP协议:就是把数据包传送给对方,而要保证确实传送到对方那里,两个重要的条件是IP地址和MAC(媒体访问控制地址)。

IP地址:指明了节点被分配到的地址,MAC地址是指网卡所属的固定地址。IP地址可以和MAC地址进行配对。IP地址可变换,但MAC地址基本不会改变。

利用ARP(地址解析协议address resolution protocol)协议凭借MAC地址进行通信

IP间的通信依赖MAC地址。

ARP协议是一种解析地址的协议,根据通信方的IP地址就可以反查出对应的MAC地址。

在到达通信目标前的中转过程中,那些计算机和路由器等网络设备只能获得很粗略的传输路线。

这种机制称为路由选择。

无论那台计算机,那台网络设备,他们都无法掌握互联网中的细节。

 1.4.2 确保可靠性的TCP协议

按层次分,TCP位于传输层,提供可靠的字节流服务(byte stream service)。

字节流服务:为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包进行管理。

可靠的传输服务是把数据准确可靠地传给对方。

TCP协议为了更容易传送大数据才把数据分割,而且TCP协议能够确认数据最终是否送达到对方。

确保数据能到达目标(TCP协议的三次握手three-way handshaking)

用TCP协议把数据包送出去后,TCP不会对传送后的情况置之不理,一定会向对方确认是否成功送达。

握手过程中使用了TCP的标志—— SYN(synchronize异步)和ACK(确认acknowledgement) 

1.  首先,发送端会发送给接收端一个带有SYN标志的数据包

2.然后,接收端收到来自发送端发送的SYN标志后,会发送给发送端带有SYN/ACK标志的数据包

3.最后,发送端确认接收端已经收到了,会发送给接收端带有ACK标志的数据包。

 1.5 负责域名解析的DNS(domain name system)服务

DNS是和HTTP协议位于同一层的协议。

它提供了域名到IP地址之间的解析服务。

用户经常使用主机名或域名来访问对方的计算机,而不是直接通过IP地址访问。

计算机既可以被赋予IP地址,也可以被赋予主机名和域名。

DNS协议通过域名查找IP地址,或者逆向从IP地址反查域名的服务。

1.6 各种协议与HTTP协议的关系 

 

1.7 URI和URL 

URI(Uniform Resource Identifier统一资源标识符)和URL(Uniform Resource Locator统一资源定位符)。其实相比于前者我们更熟悉后者。

1.7.1 URI(了解)

 URL是URI的子集。

统一资源标识符(URI)通用语法”中列举了几种 URI 例 子,如下所示。

ftp://ftp.is.co.za/rfc/rfc1808.txt 
http://www.ietf.org/rfc/rfc2396.txt 
ldap://[2001:db8::7]/c=GB?objectClass?one 
mailto:John.Doe@example.com 
news:comp.infosystems.www.servers.unix 
tel:+1-816-555-1212
telnet://192.0.2.16:80/ 
urn:oasis:names:specification:docbook:dtd:xml:4.1.2

1.7.2 URI格式


 第二章 简单的HTTP协议

2.1 HTTP协议用于客户端和服务器端之间的通信

客户端: 请求访问文本或图像等资源的一端

服务器端:提供资源相应的一端

2.2 通过请求和响应的交换达成通信 

HTTP协议规定,请求从客户端发出,最后服务器端响应应该请求并返回。

客户端发送给某个http服务器端的请求报文中的内容。 

请求报文的构成:请求的方法、请求的URI、协议版本、可选的请求首部字段和内容实体构成。 

 

HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 06:50:15 GMT Content-Length: 362
Content-Type: text/html
<html> ......

HTTP/1.1 表示服务器对应的HTTP版本。

200 OK 表示请求处理的状态码(status code)和原因短语。

下面的几行表示创建响应的日期时间,

 

响应报文由:协议版本、状态码、原因短语、响应首部字段、主体组成。

2.3 HTTP是不保存状态的协议 (无状态协议stateless)

 

 使用HTTP协议,每当发送新的请求时,就会有新的响应产生。 

HTTP协议本身不具有保留之前请求或响应报文的信息。这样可以更快的处理大量的事务。

但是在后面的实际需求中会发现,我们需要保留自己曾经登录过的信息,这就出现了cookie技术。

cookie可以管理状态,可以实现保持的登录状态。

2.4 请求 URI定位资源

 

2.5 告知服务器意图的HTTP方法 

 GET:获取资源

GET方法用来请求访问已被URI识别的资源。指定的资源经服务器端解析后返回响应内容。

如果访问的是文本,那就保持原样返回;

如果是CGI(commom getway interface),那就返回执行后的输出结果。

 

POST :传输实体主体

POST方法用来传输实体的主体。

 

PUT:传输文件 (了解即可)

put 方法用来传输文件。要求在请求报文的主体中包含文件的内容,然后保存到请求URI指定的位置。HTTP/1.1的PUT方法自身不带验证机制,任何人都可以上传文件,所以会存在安全性问题,因此一般的web网站不使用此方法。

HEAD获得报文首部 

 HEAD方法和GET方法一样,只是不返回报文的主体部分。

 

DELETE:删除文件 (了解即可)

 按照 URI删除指定的资源。

 DELETE方法和PUT方法使用一样不带验证机制,因此一般的web网站不使用此方法。

OPTIONS(选项):询问支持的方法 

 options用来查询针对请求URI指定资源支持的方法。

 

 TRACE:跟踪路径(了解就行了)

trace方法是让web服务器端之间的请求通信环回给客户端的方法。(这句话理解起来比较抽象,因此往下看吧。)

 

发送请求,在Max-Forwards首部字段中填入数值,每经过一个代理服务器就将该数字减1,当数值刚好减到0时,就停止继续传输。最后接收到请求的服务器则返回状态码200 OK的响应。

 

CONNECT :要求用隧道协议连接代理(重要)

 connect方法要求在与 代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。

主要使用 SSL和TLS协议(这两个协议可以称之为HTTPS协议)把通信内容加密后经网络隧道传输。

 connect方法的格式如下:

connect 代理服务器名:端口号 HTTP版本

2.6 使用方法下达命令 

 请求URL指定的资源发送请求报文时,采用称为方法的命令。

这里最常用的方法就是 GET POST HEAD 其次是 OPTIONS CONNECT,然后DELETE PUT TRACE了解一下即可。

 

2.7 持久连接节省通信量 

 在初始的HTTP协议中,每进行一次HTTP通信就要断开一次TCP连接。

这种情况只适用于数据访问量较少的情况,文本数量很小的传输,传输起来没有问题的。

但是对于现在来说,或者随着HTTP的普及,数据量和文件量以及访问请求较大的情况下,上面的就不再适用了。

如果在采用之前初始的HTTP协议会出现这样一个问题,每次的请求会造成无谓的TCP连接建立和断开,增加通信量的开销。

2.7.1 持久连接 

这里就提出了一个持久化连接的方法,也称为HTTP keep-alive 用于解决上述出现的问题。

 特点:只要任意一端没有提出明确的断开连接,则保持TCP连接状态。

持久连接的优点:减少TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。

在HTTP/1.1中,所有的连接默认都是持久连接。

2.7.2 管线化 

持久连接使得多数请求以管线化方式发送成为可能。

不用再等待响应就可以发送下一个请求。就可以做到同时并行发送多个请求,不需要一个一个的等待响应了。

 

 比如:请求10或者更多个图片的HTMLweb页面,用持久化连接可以让请求更快结束,而管线化技术比持久化连接还要快。

请求的数量越多,越明显。

2.8 使用Cookie的状态管理

 这里cookie主要是解决HTTP无状态协议的问题。

虽然无状态协议有缺点,但是也有优点。比如:由于无状态协议不用保存,就会减少服务器的CPU以及内存资源的消耗。其次,由于HTTP协议比较简单,会应用到各种场景中。

 通过我上面的介绍 其实就是想引出cookie技术。

cookie怎么使用?

将cookie写在请求和响应报文中来控制客户端的状态。

cookie会根据从服务器端发送过来的响应报文内有一个set-cookie的首部字段信息,就会通知客户端保存cookie。

为什么要通知客户端保存cookie呢?

因为当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入cookie值后发送出去,这个时候注意了,服务器会发现客户端发送过来的cookie后,回去检查是从哪一个客户端发送过来的连接请求,然后对比服务器上的记录,最后得出之前的状态信息。

 

上面这两张图片展示了cookie交互的情景,

下面我用HTTP请求报文和响应报文具体说明一下:

1.请求报文(没有cookie的信息状态这是第一次请求的时候) 

GET /reader/ HTTP/1.1
Host: hackr.jp 
*首部字段内没有Cookie的相关信息

2.响应报文(服务器端生成对应的cookie信息) 

HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Server: Apache
<Set-Cookie: sid=1342077140226724; path=/; 
expires=Wed, 10-Oct-12 07:12:20 GMT>
Content-Type: text/plain; charset=UTF-8

3.请求报文(带有cookie的信息了这是第二次请求时) 

GET /image/ HTTP/1.1
Host: hackr.jp
Cookie: sid=1342077140226724

第三章 HTTP报文内的HTTP信息 

什么是HTTP通信?

HTTP通信过程包括从客户端发往服务器端的请求以及服务器端返回客户端的响应

3.1 HTTP报文

 什么是HTTP报文?

用于HTTP协议交互的信息。

客户端(请求端)的HTTP报文叫做请求报文,

服务器端(响应端)的HTTP报文叫做响应报文。

看一下HTTP报文的结构:

HTTP报文 大致由三个部分组成,报文首部、报文主体、空行。首部和主体由空行来划分。

3.2  请求报文及响应报文的结构

 

图:请求报文(上)和响应报文(下)的结构 

 

分析一下请求报文和响应报文:

它们的组成:请求行(包含用于请求的方法,请求的URI和HTTP版本)、

响应行(包含表明响应结果的状态码、原因短语和HTTP版本)、

首部字段(包含表示请求和响应的各种条件和属性的各类首部)。

首部字段:请求首部、响应首部、通用首部、实体首部

3.3 编码提升传输速率

 3.3.1 报文主体和实体主体的差异

报文(message)

是HTTP通信中的基本单位,由8位组字节流组成,通过HTTP通信传输。

实体 (entity)

作为请求和响应的有效载荷数据(补充项)被传输,其内容由实体首部和实体主体组成。

HTTP报文的主体用于传输请求或响应的实体主体。

通常,报文主体等于实体主体。

只有当传输中进行编码操作时,实体主体的内容发生变化,才导致它和报文主体产生差异。

3.3.2 压缩传输的内容编码

向待发送邮件内增加附件时,为了使邮件容量变小,我们会先用zip压缩文件之后再添加附件发送。

 

3.3.3 分割发送的分块传输编码 

 在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。

这种把实体主体分块的功能称为分块传输编码。

分块传输编码会将实体主体分成多个块,每一块都会用十六进制来标记块的大小。

使用分块传输编码的实体主体会由接收的客户端负责编码,恢复到编码前的实体主体。

 3.4 发送多种数据的多部分对象集合

多用途因特网邮件扩展(MIME  Multipurpose  Internet mail extensions) 

解释一下:允许邮件处理文本、图片、视频等多个不同类型数据。

在MIME扩展中会使用一种称为多部分对象集合的方法,来容纳多份不同类型的数据。

同样的。HTTP协议中也采纳了多部分对象集合,发送的一份报文主体内可含有多类型实体。

在图片或文本文件等上传时使用。

看一下下面使用的两种对象

multipart/from-data和multipart/byterranges

multipart/from-data——在web表单文件上传时使用。

Content-Type: multipart/form-data; 
boundary=AaB03x  
--AaB03x
Content-Disposition: 
form-data; name="field1"
 
Joe Blow
--AaB03x
Content-Disposition: form-data; 
name="pics"; filename="file1.txt" 
Content-Type: text/plain
 
...(file1.txt的数据)...
--AaB03x--

 multipart/byterranges——状态码206响应报文包含了多个范围的内容时使用

HTTP/1.1 206 Partial Content
Date: Fri, 13 Jul 2012 02:45:26 GMT
Last-Modified: Fri, 31 Aug 2007 02:02:20 GMT
Content-Type: multipart/byteranges; 
boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-Type: application/pdf 
Content-Range: bytes 500-999/8000
..(范围指定的数据)... 
--THIS_STRING_SEPARATES 
Content-Type: application/pdf 
Content-Range: bytes 7000-7999/8000
...(范围指定的数据)... 
--THIS_STRING_SEPARATES--

注意点:

1. 使用多部分对象集合时候,一定要在首部字段中加入Content-type,他指明了要连接的对象的类型。

2. boundary(界线):来划分多部分对象集合指明的各类实体——这句话什么意思,我感觉不好理解,那就往下看吧。

举个例子:就拿上面的例子来说,

boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES   在各个起始行之前插入 -- 标记这里是THIS_STRING_SEPARATES

Content-Type: application/pdf
 
Content-Range: bytes 500-999/8000

..(范围指定的数据)... 

--THIS_STRING_SEPARATES 

Content-Type: application/pdf 

Content-Range: bytes 7000-7999/8000

...(范围指定的数据)... 

--THIS_STRING_SEPARATES--   在最后插入 -- 标记--THIS_STRING_SEPARATES-- 作为结束。

3.5 获取部分内容的范围请求

介绍一下背景:

在很久很久以前(反正就是很久之前),用户不能使用现在这种高速的带宽访问互联网,在当时,下载 一个稍微大的图片就已经很吃力了,要是在下载的过程中遇到网络中端或者没有网络的情况,那就要重新从头下载这个文件。

理由:这个时候为了解决这个问题呢,需要一种恢复机制。

恢复机制的概念:就是指能从刚才下载中断的地方回复下载。

怎么才能应用呢?

要实现该功能需要指定下载的实体范围。

范围请求:指定范围发送的请求。

例子:

比如对一份10000字节大小的资源,如果使用范围请求,可以只请求5001~10000字节内的资源。

执行范围请求时,会用到首部字段Range来指定资源的byte范围。

byte范围的形式:

第一种形式:5001~10000字节:

Range: bytes=5001-10000

2. 从5001字节之后的全部的

Range: bytes=5001-

3. 从一开始到3000字节和5000~7000字节的范围

Range: bytes=-3000, 5000-7000

前两种只是单纯的范围请求,参照上面的就可以了。这是请求范围响应成功的情况下会返回206 Partial Content

要是在请求范围不成功的情况下呢?

会返回状态码200 OK和完整的实体内容。

最后那个是多范围请求,响应会在首部字段Content-type标明multipart/byteranges后返回响应报文。

3.6 内容协商返回最合适的内容

引出:一个web页面可能存在着多份相同内容的页面。

比如,中文版和英文版web页面。

唯一区别就是,语言的不同。

 内容协商机制:依据的是响应资源的语言、字符集、编码方式等。

三种类型:

服务器驱动协商:由服务器端进行内容协商。

客户端驱动协商:由客户端进行内容协商的方式

通明协商:是服务器驱动和客户端驱动的结合体,是由服务器端和客户端各自进 行内容协商的一种方法。


第四章 ——返回结果的HTTP状态码 

4.1 状态码告知此服务器返回的请求结果

客户端向服务器端发送请求时,返回的状态结果。

通过状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。

状态码由三位数字和原因短语组成。

看一下状态码的类别:

类别原因短语
1xxInformational(信息性状态码)接收的请求正在处理
2xxSucess(成功状态码)请求正常处理完毕
3xxRedirection(重定向状态码)需要进行附加操作已完成请求
4xxClient Error(客户端错误状态码)服务器无法处理请求
5xxServer Error(服务器错误状态码)服务器请求处理错误

 4.2   2XX成功(请求正常处理完毕)

 下面介绍最常用的几个:

1. 200 OK

客户端发送给服务器端的请求被正常处理了。

2.  204 No Content 

 

表示:虽然发送请求处理成功了,但是 没有资源(内容)返回给客户端。

3.  206 Partial Content (部分内容通常指范围请求)

 

 这里指的是客户端进行的范围请求,服务器端成功执行了这部分的get请求。

4.3 3XX重定向 (需要的附加操作已完成请求处理)

1. 301 Moved Permanently (永久性重定向) 

 

2.  302 Found (临时性重定向) 

 3. 303 See Other

 

303明确表示客户端应当采用GET方法获取资源。这是和302的区别。

4. 304 Not Modified  

 

 这个其实和重定向没关系,只是被划分为 304。

5. 307 Temporary Redirect(临时重定向)

 4.4 4XX 客户端错误

1. 400 Bad Request

 

 表示请求报文中存在语法错误。需要修改内容后再次发送请求。

2. 401 Unauthorized(未认证) 

 

 发送的请求需要有HTTP认证的认证信息。

 3. 403 Forbidden(请求资源的访问被服务器拒绝了)

4. 404 Not Found (非常重要——表示没有找到请求的资源)

4.5 5XX服务器错误 

 1. 500 Internal Server Error(服务器端在执行时发生了错误)

2. 503 Service Unavailable(服务器不可用/处于停机维护/处于超负载) 

 


第五章 与HTTP协作Web服务器 

 一台web服务器上面可搭建多个独立域名的web网站,也可作为通信路径上的中转服务器提升传输效率。

5.1 用单台虚拟主机实现多个域名

HTTP/1.1规范允许一台HTTP服务器搭建多个web站点。

比如:提供web托管服务的供应商,可以利用一台服务器为多为客户服务,也可以以每位客户持有的域名运行各自不同的网站,这是因为利用了虚拟主机的功能。

虽然物理层面只有一台服务器,但是只要使用虚拟主机的功能,则可以假象已具有多台服务器。

 客户端使用HTTP协议访问服务器时,会经常采用类似www.hackr.jp这样的主机名和域名。

在互联网上,域名通过DNS服务器映射到IP地址(域名解析)之后访问目标网站。

如果一台服务器 内托管了两个域名,当收到请求时,就要弄清楚究竟要访问那个域名。

5.2 通信数据转发程序:代理、网关、隧道

在HTTP通信时,除了客户端和服务器外,还有一些用于通信数据转发的应用程序,上面的这三个,配合服务器工作。

代理:具有转发的功能,在客户端和服务器端扮演着”中间人“的角色。接收从客户端发送给服务器端的请求,并把请求发送给服务器,同时也接收服务器返回的响应,并把响应发送给客户端。

网关:接收从客户端发送来的请求时,网关就像自己拥有资源的服务器一样,对请求进行处理。

 隧道:在距离非常远的客户端和服务器两者之间进行中转,并保持通信连接的应用程序。

5.2.1 代理

 代理服务器器就是接收客户端发送的请求后转发给其他服务器,把请求的URI直接发送给持有资源的目标服务器。

资源的目标服务器就是源服务器。从源服务器返回的响应经过代理服务器返回给客户端。

 为什么要使用代理服务器(proxy)呢?

要利用缓存技术减少网络的带宽的流量,组织内部针对特定网站的访问控制,以获取访问日志为主要目的,等等。

代理按照两种基准分类:是否使用缓存;是否会修改报文。 

 缓存代理:

缓存代理就是先将资源的副本保存到代理服务器上。

当代理再次接收到相同资源请求时,就可以不从源服务器那里获取资源,直接将缓存的资源作为响应返回。

透明代理(transparent proxy):

转发请求或响应时,不对报文做任何处理的代理类型被称为透明代理,反之,则为非透明代理。

5.2.2 网关

网关可以使通信线路上的服务器提供非HTTP协议服务。

网关可以提高通信的安全性,在客户端与网关之间的通信线路上加密以确保连接的安全。

比如:利用网关可以连接数据库,查询SQL语句;也可以和信用卡结算进行系统联动。

5.2.3 隧道 

目的就是确保客户端和服务器端进行安全的通信。

使用SSL进行加密通信。

隧道不会去解析HTTP请求,请求会保持原样的发送给之后的服务器。

 

 5.3 保存资源的缓存

缓存是代理服务器或客户端本地磁盘内保存的资源副本。利用缓存可减少对源服务器的访问,因此可以节省通信流量和通信时间。

 

 缓存服务器是代理服务器的一种。

缓存服务器的优势:利用缓存可以避免多次从源服务器转发资源。客户可以直接从缓存服务器上获取资源,源服务器也不必多次处理相同的请求。

5.3.1 缓存的有效期

即使缓存服务器内有缓存,也不能保证每次都会有返回对同资源的请求。

这就关系到缓存资源的有效性问题了。

如果源服务器上的资源更新时,如果还是使用不变的缓存,那就回变成以前的资源(意思是缓存失效了)。

 这个时候就需要重新向源服务器上获取新的缓存资源了。

5.3.2 客户端的缓存

缓存还可以存在于客户端中。比如:以 Internet Explorer 程序为例,把客户端缓存称为临时网络文件 (Temporary Internet File)。

浏览器缓存如果有效,就不必在向服务器请求相同的资源了,可以直接在本地磁盘内读取。

如果失效就和上面的相同了。浏览器会再次请求新的资源。

 


第六章 HTTP首部 

6.1 HTTP报文首部

 HTTP协议的请求和响应报文中必定包含HTTP首部。首部内容为客户端和服务器分别处理请求和响应提供所需要的信息。

请求报文首部具体的信息我写出来吧,其实了解一下就行,知道代表什么意思就行。

GET / HTTP/1.1

Host: hackr.jp

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Ge Accept: 

text/html,application/xhtml+xml,application/xml;q=0 

Accept-Language: ja,en-us;q=0.7,en;q=0.3

Accept-Encoding: gzip, deflate

DNT: 1

Connection: keep-alive

If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT 

If-None-Match: "45bae1-16a-46d776ac"

Cache-Control: max-age=0

HTTP响应报文 

 

​​​​HTTP/1.1 304 Not Modified
Date: Thu, 07 Jun 2012 07:21:36 GMT Server: Apache
Connection: close
Etag: "45bae1-16a-46d776ac"

 6.2 HTTP首部字段

 6.2.1 HTTP 首部字段传递重要信息

 

6.2.2 HTTP 首部字段结构 

 首部字段名:字段值1,字段值2,...

6.2.3      4种HTTP首部字段类型

请求首部字段(request header fields)

响应首部字段 (response header fields)

 通用首部字段(general header fields)

 实体首部字段(entity header fields)

6.2.4 HTTP/1.1 首部字段一览(由于太多的字段了,我只写出主要的和常见的字段)

1. 通用首部字段 

首部字段名

说明

Cache-Control

控制缓存的行为

Connection

逐跳首部、连接的管理

Date

创建报文的日期时间

Warning

错误通知

2:请求首部字段 

首部字段名

说明

Accept

用户代理可处理的媒体类型
Accept-Charset优先的字符集
Accept-Encoding优先的内容编码
Accept-Language优先的语言(自然语言)
AuthorizationWeb认证信息

Host

请求资源所在服务器

If-Match

比较实体标记(ETag)

If-Modified-Since

比较资源的更新时间

If-None-Match

比较实体标记(与 If-Match 相反)

If-Range

资源未更新时发送实体 Byte 的范围请求

If-Unmodified-Since

比较资源的更新时间(与If-Modified-Since相反)

Max-Forwards

最大传输逐跳数

Proxy-Authorization

代理服务器要求客户端的认证信息

Range

实体的字节范围请求

 3:响应首部字段

首部字段名

说明

Accept-Ranges

是否接受字节范围请求

Age

推算资源创建经过时间

Location

令客户端重定向至指定URI

Proxy-Authenticate

代理服务器对客户端的认证信息

Server

HTTP服务器的安装信息

Vary

代理服务器缓存的管理信息

WWW-Authenticate

服务器对客户端的认证信息

4:实体首部字段

首部字段名

说明

Allow

资源可支持的HTTP方法

Content-Encoding

实体主体适用的编码方式

Content-Language

实体主体的自然语言

Content-Length

实体主体的大小(单位:字节)

Content-Location

替代对应资源的URI

Content-Range

实体主体的位置范围

Content-Type

实体主体的媒体类型

Expires

实体主体过期的日期时间

Last-Modified

资源的最后修改日期时间

6.2.5 非 HTTP/1.1 首部字段——这个了解就行

6.2.6 End-to-end 首部和 Hop-by-hop 首部(了解)

HTTP 首部字段将定义成缓存代理和非缓存代理的行为,分成 2 种类型。

端到端首部

逐跳首部

6.3 HTTP/1.1 通用首部字段 

1. Cache-Control——缓存的控制

 

这里我列举了几个常见的缓存请求指令和缓存响应指令

private指令:

no-cache 指令 :

为了防止从缓存中返回过期的资源。

max-age指令 

 

min-fresh指令 

 

要求缓存服务器返回至少还未过指定时间的缓存资源。 


6.3.2 Connection

作用:

1. 控制不再转发给代理的首部字段。

2. 管理持久连接

控制不再转发给代理的首部字段

 Connection:不再转发的首部字段名。

客户端发送请求和服务器返回响应内,使用Connection首部字段,可控制不再转发给代理的首部字段。

管理持久连接

HTTP/1.1版本默认连接都是持久连接。客户端会在持久连接上发送请求。当服务器端想明确断开连接时,则指定Connection 首部字段的值为close。

 

 

 HTTP/1.1之前的HTTP版本的默认连接都是非持久连接。如果想在HTTP/1.1之前的协议上维持持久连接,则需要指定Connection首部字段的值为keep-alive。

6.3.3 Date(表明创建HTTP报文的日期和时间)

 6.3.4 Pragma(这个字段是HTTP/1.1之前的版本)

如果是HTTP/1.1的话,会发送Cache- Control: no-cache指定缓存的处理方式最为理想。

一般发送的请求会包含下面两个首部字段

Cache-Control: no-cache
Pragma: no-cache

 

6.3.5 Trailer (预告)

 会事先说明在报文主体后记录了那些首部字段。应用在HTTP/1.1版本分快传输编码时。

6.3.6 Transfer-Encoding

 传输报文主体时采用的编码方式,仅对分块传输编码有效。

 6.3.7 Upgrade

检测HTTP协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。

使用首部字段Update时,还需要指定Connection:Update。

6.3.8 Via 

 追踪客户端与服务器之间的请求和响应报文的传输路径。

Via 不仅用于追踪报文的转发,还可避免请求回环的发生。所以必须正在经过代理时附加该首部字段内容。

经过代理服务器A时,Via首部附加了“1.0 gw.hackr.jp (Squid/3.1)”这样的字符串值。

行头的 1.0 是指接收请求的服务器上应用的 HTTP 协议版本。

接下来经过代理服务器 B 时亦是如 此,在 Via 首部附加服务器信息,也可增加 1 个新的 Via 首部写入服 务器信息。

 6.3.9 Warning

 Warning 首部的格式如下。最后的日期时间部分可省略。

Warning: [警告码][警告的主机:端口号]“[警告内容]”([日期时间])

Warning: 113 gw.hackr.jp:8080 "Heuristic expiration" Tue, 03

 


6.4 请求首部字段 

请求首部字段是从客户端往服务器端发送请求报文中所使用的字段。

 

 6.4.1 Accept

Accept 首部字段可通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。

 当服务器提供多种内容时,将会首先返回权重值最高的媒体类型。

6.4.2 Accept-Charset

 

 Accept-Charset首部字段可用来通知服务器用户代理支持的字符集及字符集的相对优先顺序。

6.4.3 Accept-Encoding

Accept-Encoding首部字段用来告知服务器用户代理支持的内容编码及内容编码的优先级顺序。

6.4.4 Accept-Language 

 

首部字段Accept-Lnguage用来告知服务器用户代理能够处理的自然语言集(指中文或英文等),以及自然语言集的相对优先级(权重)。可一次性处理多种语言。

6.4.5 Authorization 

  该字段告知服务器,用户代理的认证信息。

6.4.6 Expect(期望)

客户端使用首部字段except 来告知服务器,期望出现的某种特定行为。

6.4.7 From 

from  用来告知服务器使用用户代理的用户的电子邮件地址。

6.4.8 Host 

 告知服务器,请求的资源所处的互联网主机名和端口号。

请求被发送至服务器时,请求中的主机名会用IP地址直接替换解决。但如果这时 ,相同的IP地址下部署运行着多个域名,那么服务器就会就会无法理解究竟是哪个域名对应的请求。因此,就需要使用Host来明确指出请求的主机名。若服务器没有设定主机名,那就直接发送一个空值。

 6.4.9 If-Match

If-xxx这种样式请求,都可称为条件请求。服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。

 6.4.10 If-Modified-Since

如果 If-Modified-Since字段值早于资源的更新时间,则希望处理该请求。

 如果指定If-Modified-Since字段值的日期时间之后,如果请求资源都没有过更新,则返回状态码304。

6.4.11 If-None-Match

与If-Match相反,只要请求的资源不一致,就告知服务器处理该请求。

6.4.12 If-Range  

 如果请求一致则作为范围请求处理,反之,则返回全体资源。 

 上面的这种要请求两次,效率会降低,花费的时间也会比较多,所以了解即可。

6.4.13 If-Unmodified-Since

和If-Modified-Since相反,告知服务器,指定的请求资源只有在字段值内指定的日期时间之后,未发生更新的情况下,才能处理请求。

6.4.14 Max-Forwards

 

使用HTTP协议通信时,请求可能会经过代理等多台服务器。途中,如果代理服务器由于某些原因导致请求失败,客户端也就等不到服务器返回的响应了。 

当服务器接收到 Max-Forwards 值为 0 的请求 时,则不再进行转发,而是直接返回响应。 

 

 6.4.15 Proxy-Authorization

 接收从代理服务器发来的认证资质时,客户端会发送包含首部字段Proxy-Authorization请求,

告知服务器认证所需要的信息。

6.4.16 Range 

 获取部分资源的范围请求,告知服务器资源的指定范围。

6.4.17 Referer (参考者)了解就行

告知服务器请求的原始资源的URI

 6.4.18 TE(了解)

首部字段 TE 会告知服务器客户端能够处理响应的传输编码方式及相 对优先级。 

6.4.19 User-Agent 

 首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传 达给服务器。


6.5 响应请求字段 

 响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息,以及对客户端的附加要求等信息。

 6.5.1 Accept-Ranges

告知客户端服务器是否能处理范围请求,以指定获取服务端某个部分的资源。

可指定的字段值有两种,可处理的范围请求时指定其为bytes,反之则指定其为none。

6.5.2 Age 

 告知客户端,源服务器在多久前创建了响应。单位为秒。

6.5.3 ETag 

告诉客户端实体标识。

强ETag值 和弱ETag值 

强ETag值:不论实体发生多么细微的变化都会改变其值。ETag: "usagi-1234"

弱ETag值:只有资源发生了根本改变,产生差异时才会改变ETag值。ETag: W/"usagi-1234"

6.5.4 Location 

 可以将响应接收方引导至某个与请求URI位置不同的资源。

6.5.5 Proxy-Authenticate

会把由代理服务器所要求的认证信息发送给客户端。

6.5.6 Retry-After  

 告知客户端应该在多久之后再次发送请求。

 6.5.7 Server

 告知客户端当前服务器上安装的HTTP服务器应用程序的信息。

6.5.8 Vary 

 当代理服务器接收到带有 Vary 首部字段指定获取资源的请求 时,如果使用的 Accept-Language 字段的值相同,那么就直接从缓存返回响应。反之,则需要先从源服务器端获取资源后才能作为响应返回。

6.5.9 WWW-Authenticate


6.6 实体首部字段 

实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部。

 

6.6.1 Allow 

告知客户端能够支持Request-URI指定资源的所有HTTP方法。

6.6.2 Content-Encoding

告知客户端服务器对实体的主体部分选用的内容编码方式。像,gzip compress deflate identity

6.6.3 Content-Language

 

告知客户端,实体主体使用的自然语言(中文或英文) 

 6.6.4 Content-Length

 

实体主体部分的大小(单位是字节)。

6.6.5 Content-Location 

 Content-Location: http://www.hackr.jp/index-ja.html

给出与报文主体部分相对应的URI。

这个是报文主体返回资源对应的URI。 


6.6.6 Content-MD5

图:客户端会对接收的报文主体执行相同的 MD5 算法,然后与首 部字段 Content-MD5 的字段值比较。首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检 查报文主体在传输过程中是否保持完整,以及确认传输到达。

6.6.7 Content-Range

 6.6.8 Content-Type

实体主体内对象的媒体类型。

6.6.9 Expires

 会将资源失效的日期告知客户端。

6.6.10 Last-Modified

 

资源最终修改的时间。

6.7 为Cookie 服务的首部字段 

 Cookie的工作机制是用户识别及状态管理。Web网站为了管理用户的状态会通过Web浏览器,把一些数据临时写入用户的计算机内。

接着当用户访问该web网站时,可通过通信方式取回之前发放的Cookie。

 6.7.1 Set-Cookie

6.7.2 Cookie 

首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。 

 6.8 其他首部字段

X-Frame -Options

X-XSS-Prote ction

DNT
P3P

6.8.1  X-Frame -Options

首部字段 X-Frame-Options 属于 HTTP 响应首部,用于控制网站内容 在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防 止点击劫持(clickjacking)攻击。

首部字段 X-Frame-Options 有以下两个可指定的字段值。

DENY(deny) :拒绝

SAMEORIGIN(sameorigin同源) :仅同源域名下的页面(Top-level-browsing- context)匹配时许可。

6.8.2 X-XSS-Prote ction

首部字段 X-XSS-Protection 属于 HTTP 响应首部,它是针对跨站脚本 攻击(XSS)的一种对策,用于控制浏览器 XSS 防护机制的开关。

首部字段 X-XSS-Protection 可指定的字段值如下。

0 :将 XSS 过滤设置成无效状态
1 :将 XSS 过滤设置成有效状态

6.8.3 DNT

 首部字段 DNT 属于 HTTP 请求首部,其中 DNT 是 Do Not Track 的简 称,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方 法。

首部字段 DNT 可指定的字段值如下。

0 :同意被追踪

1 :拒绝被追踪

6.8.4 P3P

首部字段 P3P 属于 HTTP 相应首部,通过利用 P3P(The Platform for Privacy Preferences,在线隐私偏好平台)技术,可以让 Web 网站上 的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的 目的。

要进行 P3P 的设定,需按以下操作步骤进行。

步骤 1:创建 P3P 隐私

步骤 2:创建 P3P 隐私对照文件后,保存命名在 /w3c/p3p.xml

步骤 3:从 P3P 隐私中新建 Compact policies 后,输出到 HTTP 响应 中


第七章 确保Web 安全的HTTPS 

在 HTTP 协议中有可能存在信息窃听或身份伪装等安全问题。使用 HTTPS 通信机制可以有效地防止这些问题。

7.1 HTTP的缺点 

1. 通信使用明文(不加密),内容可能会被窃听

2. 不验证通信方的身份,因此有可能遭遇伪装

3. 无法证明报文的完整性,所以有可能已遭篡改。

这些问题不仅会出现在HTTP上,其他未加密的协议中也会存在这类问题。

7.1.1 通信使用明文可能会被窃听

由于http本身不具备加密的功能,所以无法做到通信整体进行加密。HTTP报文使用明文方式发送。

TCP/IP是可能被窃听的网络

为什么通信时不加密?

这是一个缺点,按照TCP/IP的工作机制,通信内容在所有通信线路上都有可能会遭到窥视。

互联网其实就是连通到全世界的网络。无论在世界的任何角落,当服务器与客户端进行通信时,通信线路上的所有设备都不可能是自己的私有物品,所以不排除会遭到窥视的行为。

即使已经经过加密处理的通信,也会被窥视,其实这和未加密的通信是相同的。只是经过加密的通信,会让人无法破解报文的信息,但加密处理后的报文信息本身还是会被看到。

窃听相同段上的通信并非难事,只需要收集在互联网上流动的数据包就行了。

收集来的数据包的解析工作,交给抓包工具就行了。

加密处理防止被窃听

通信的加密:

HTTP中没有加密机制,但可以通过和SSL(Secure Socket Layer安全套接层)和TLS(Transport Layer Security安全层传输协议)的组合使用,加密HTTP的通信内容。

与SSL组合使用的HTTP被称为HTTPS(超文本传输安全协议)

内容的加密 

 把HTTP报文里所含的内容进行加密处理。加密后在发送请求。

要做到有效的加密,客户端和服务器端同时具有加密和解密的机制。

注意:由于内容加密不同于前面所说的通信加密,内容有可能会被篡改。

7.1.2 不验证通信方的身份就可能遭遇伪装

HTTP中的请求和响应不会对通信方进行确认。

任何人都可发起请求 

HTTP协议的实现本身非常简单,不论是谁发送过来的请求都会返回响应。

会存在以下各种隐患:

1. 无法确定请求发送至目标的web服务器是否按照真实意图返回响应的那台服务器。有可能是伪装的web服务器。

2.  无法确定响应返回到的客户端是否是按真实意图接收响应的那个客户端。有可能是已伪装的客户端。

3. 无法确定正在通信的对方是否具备访问权限。

4. 无法确定请求是来自何方、出自谁手。

5. 即使是无意义的请求也会照单全收。无法阻止海量请求下的Dos攻击。

查明对手的证书

虽然使用HTTP协议无法确定通信方,但如果使用SSL则可以。

证书由值得信任的第三方机构颁发,用以证明服务器和客户端是实际存在的。

使用证书,以证明通信方就是意料中的服务器。这对使用者来说,也减少了个人信息泄露的危险性。

7.1.3 无法证明报文完整性,可能已遭篡改

 完整性:是指信息的准确度。若无法证明其完整性,也就意味着无法判断信息是否准确。

接受到的内容可能有误

HTTP协议无法证明通信的报文的完整性,因此,在请求或响应送出之后直到对方接收之前的这段时间内,即使请求或响应遭到篡改,也没有办法获悉。

 比如:从每个web网站上下载内容,是无法确定客户端下载的文件和服务器存放的文件是否前后一致。文件内容在传输途中可能已经被篡改为其他的内容。即使内容真的已经改变,作为接收方的客户端也是察觉不到的。

中间人攻击:请求或响应在传输途中,遭攻击者拦截并篡改内容的攻击。

 

如何防止篡改  

虽然有使用HTTP协议确定报文完整性的方法,但事实上并不方便捷、可靠。其中常用的是MD5和SHA-1等散列值校验的方法,以及用来确认文件的数字签名方法。

但是用这些方法也依然无法百分之百保证确认结果正确。

下面就要引入HTTPS。

SSL提供认证和加密处理及摘要功能。 


7.2 HTTP+加密+认证+完整性保护=HTTPS 

7.2.1 HTTP加上加密处理和认证以及完整性保护后即是HTTPS

如果在HTTP协议通信中使用未经加密的明文,比如在web页面中输入信用卡号,如果这条线路在通信时遭到窃听,那么信用卡号就回暴露。

对于HTTP来说,服务器也好,客户端也好,都是没有办法确认通信方的。

为了解决上述出现的问题,需要在HTTP上再加入加密处理和认证等机制。

添加了加密和认证机制的HTTP成为HTTPS。

经常会在web的登录页面和购物车结算界面等使用HTTPS通信。

使用HTTPS通信时,不再使用http:// 而是改用 https://

其次,当浏览器访问HTTPS通信有效的web网站时,浏览器的地址栏内会出现一个带锁的标志。

7.2.2 HTTPS是身披SSL外壳的HTTP

HTTPS并不是应用层的一种新的协议,只是HTTP + SSL + TLS 组合而已。

HTTP直接与TCP通信。当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了。

7.2.3 相互交换密钥的公开密钥加密技术

SSL采用一种叫做公开密钥加密(Public-key cryptography)的加密处理方式。

近代的加密方法中加密算法是公开的,而密钥却是保密的。 

 通过这种方式得以保持加密方法的安全性。

加密和解密都会用到密钥。没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。如果密钥被攻击者获得,那加密也就失去了意义。

共享密钥加密的困境

加密和解密同用一个密钥的方式称为共享密钥加密,也被叫做密钥加密。

以共享密钥加密时必须将密钥也发给对方。但是怎么样才能安全地转交?在互联网上转发密钥时,如果通信被监听那么密钥就可能会落入到攻击者之手,同时也就失去了加密的意义。另外还得设法安全地保管接收到的密钥。

 

 使用两把密钥的公开密钥加密

公开密钥加密方式很好地解决了共享密钥加密的困难

公开密钥加密使用一对非对称的密钥。一把叫做私有密钥(private key),另一把叫做公开密钥(public key)。私有密钥不能让任何人知道,公开密钥则可以随意发布,任何人都可以获得。

使用公开密钥加密方式,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。

HTTPS采用混合加密机制 

共享密钥加密和公开密钥加密两者混合使用进行混合加密机制。

若密钥能够实现安全交换,那么有可能会考虑仅使用公开密钥加密来通信。

但是公开密钥加密与共享密钥加密相比,其处理速度要慢。

要充分利用两者各自的优势,将多种方法组合起来用于通信。

在交换密钥的时候使用公开密钥加密,在建立通信的时候使用共享密钥加密。

7.2.4 证明公开密钥正确性的证书

公开密钥加密方式还是存在一些问题的。那就是无法证明公开密钥本身就是真正的公开密钥。

比如:正准备和某台服务器建立公开密钥加密方式下的通信时,如何证明是哦到的公开密钥就是原本预想的那台服务器发行的公开密钥。或许在公开密钥传输途中,真正的公开密钥已经被攻击者替换掉了。

为了解决上述问题,可以使用由数字证书认证机制(CA Certificate Authority) 和其相关的机关颁发的公开密钥证书。

可证明组织真实性的EV SSL证书

证书的一个作用是用来证明作为通信一方的服务器是否规范,另一个作用是可确认对方服务器背后运营的企业是否真实存在。拥有该特性的证书就是 EV SSL证书。

用以确认客户端的客户端证书

 HTTPS中还可以使用客户端证书。以客户端证书进行客户端认证,证明服务器正在通信的对方始终是预料之内的客户端。

但是客户端证书的几处问题点:第一个是证书的获取及发布——需要付费购买。

第二个问题点是:客户端证书毕竟只能用来证明客户端实际存在,而不能用来证明本人的真实有效性。也 就是说,只要获得了安装有客户端证书的计算机的使用权限,也就意味着同时拥有了客户端证书的使用权限。

认证机构信誉第一

由自认证机构颁发的证书称为自签名证书

中级认证机构的证书可能会变成自认证证书

7.2.5 HTTPS的安全通信机制

看一下HTTPS的通信步骤

步骤1: 客户端通过发送Client Hello报文开始SSL通信

步骤2: 服务器可进行SSL通信时,会以Server Hello 报文作为应答。

步骤3:之后服务器发送Certificate报文。报文中包含公开密钥加密。

步骤4:最后服务器发送Server Hello Done 报文通知客户端,最初阶段的SSL握手协商部分结束。

步骤5:SSL第一次握手之后客户端以Client Key Exchange 报文作为回应。

步骤6: 接着客户端继续发送Change Cipher Spec 报文。

步骤7:客户端发送Finished报文

步骤8:服务器同样发送 Change Cipher Spec报文

步骤9:服务器同样发送Finished报文

步骤10: 服务器和客户端的Finished报文交换完毕后,SSL连接就算成功。

步骤11:应用层协议通信,即发送HTTP响应。

步骤12:最后客户端断开连接

在以上流程中,应用层发送数据时会附加一种叫做MAC(Message Authentication Code)的报文摘要。MAC能够查知报文是否遭到篡改,从而保护报文的完整性。

SSL和TLS

HTTPS使用SSL和TLS这两个协议。

SSL速度慢吗?

HTTPS也存在一些问题,那就是当使用SSL时,它的处理速度会变慢。

SSL慢分两种。一种是指通信慢。另一种是指由于大量消耗CPU及内存等资源,导致处理速度变慢。

和使用HTTP相比,网络负载可能会变慢2到100倍。除去和TCP连接、发送HTTP请求,响应以外,还必须进行SSL通信,因此整体上处理通信量不可避免会增加。

另一点是SSL必须进行加密处理。

为什么不一直使用HTTPS

 其中一个原因是,因为与纯文本通信相比,加密通信会消耗更多的CPU及内存资源。如果每次通信都加密,会消耗相当多的资源,那么请求数量必定会随之减少。

所以如果是非敏感信息使用HTTP通信,只有在包含个人信息等敏感数据时,才利用HTTPS加密通信。

特别是每当那些访问量较多的web网站在进行加密处理时,它们所承担的负载不容小觑。

在进行加密处理时,并非对所有内容都进行加密处理,而是仅在需要信息隐藏时才会加密,以节约资源。

除此之外,想要节约购买证书的开销也是原因之一。

要进行HTTPS通信,证书是必不可少的。而使用的证书必须向认证机构(CA购买)。


第八章——确认访问用户身份的认证

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值