HTTP协议详解

Web安全基础是渗透测试工程师需要掌握的主题知识内容之一,通过本部分的学习,应当掌握:

l  了解HTTP协议的基础知识,掌握HTTP协议在实际工作中的使用

l  掌握注入漏洞相关知识以及相关的漏洞修复方法

l  掌握XSS漏洞的多种形式和防御方法

l  掌握请求伪造漏洞的危害和相应的检测方法

l  掌握文件处理漏洞的分类和代码审计方法l 掌握访问控制漏洞的分类和漏洞防御方法

l  掌握会话管理漏洞的特性和防护方法 

1 HTTP协议

知识体:WEB安全基础

 

    HTTP协议,即超文本传输协议(Hypertexttransfer protocol)。 是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议 。

 

1.1 HTTP请求方法

HTTP1.0的请求方法

(1)HTTP1.0三种请求方法

HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。

GET:请求指定的页面信息,并返回实体主体。

POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

HEAD:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头。

(2)GET请求的标准格式

    GET是最常用的方法,它的作用是获取服务器中的某个资源.下图显示了一个例子,在这个例子中,客户端用GET方法发起了一次HTTP请求,然后服务端将对应的资源返回给客户端.

GET Request-URI HTTP/1.1

上图中客户端请求的资源是www.devtf.cn/articles路径下的123.html,服务端将123.html返回给客户端.需要注意的是,GET请求的参数都需要放到请求的URL中,第一个参数之前有一个”?”,参数的格式为: 参数名=参数值,参数之间通过”&”连接. 例如,我们在请求 www.devtf.cn/articles/123.html 时希望传递用户名和用户id两个参数,那么格式应该是这样的: www.devtf.cn/articles/123.html?username=myname&userid=123 .


(3)POST请求提交表单,上传文件的方法 

    服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式*编码*,再对主体进行解析。所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。

 

application/x-www-form-urlencoded

 

    最基本的form表单结构,用于传递字符参数的键值对,请求结构如下

1

POST  HTTP/1.1Host: www.demo.comCache-Control: no-cachePostman-Token: 81d7b315-d4be-8ee8-1237-04f3976de032Content-Type: application/x-www-form-urlencodedkey=value&testKey=testValue

    请求头中的Content-Type设置为application/x-www-form-urlencoded; 提交的的数据,请求body中按照 key1=value1&key2=value2 进行编码,key和value都要进行 urlEncode;

 

multipart/form-data

 

    这是上传文件时,最常见的数据提交方式,看一下请求结构

1

2

3

4

POST  HTTP/1.1Host: www.demo.comCache-Control: no-cachePostman-Token: 679d816d-8757-14fd-57f2-fbc2518dddd9Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name="key"value------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name="testKey"testValue------WebKitFormBoundary7MA4YWxkTrZu0gW

Content-Disposition: form-data; name="imgFile"; filename="no-file"Content-Type: application/octet-stream<data in here>------WebKitFormBoundary7MA4YWxkTrZu0gW--

首先请求头中的Content-Type 是multipart/form-data; 并且会随机生成一个boundary, 用于区分请求body中的各个数据; 每个数据以 –boundary 开始, 紧接着换行,下面是内容描述信息, 接着换2行, 接着是数据; 然后以 –boundary– 结尾, 最后换行;

文本数据和文件,图片的内容描述是不相同的 
文本参数:

1

Content-Disposition: form-data; name="key"Content-Type: text/plain; charset=UTF-8Content-Transfer-Encoding: 8bit

文件参数:

1

Content-Disposition: form-data; name="imgFile"; filename="no-file"Content-Type: application/octet-streamContent-Transfer-Encoding: binary

 


(4)HEAD请求与GET请求的区别

HEAD方法与GET方法的行为很类似,但服务器在响应中只返回首部. 不会返回实体的主体部分. 这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查. 使用HEAD可以在不获取资源的情况下了解资源的情况(比如,判断其类型); 通过查看响应中的状态码,看看某个对象是否存在; 通过查看首部,测试资源是否被修改了. 服务器开发者必须确保返回的首部与GET请求所返回的首部完全相同. 遵循HTTP/1.1规范,就必须实现HEAD方法. 如下图所示.


HTTP1.1新增的请求方法

(1)HTTP1.1新增了五种请求方法

OPTIONS, PUT, DELETE,TRACE 和 CONNECT 方法的基本概念 

OPTIONS:允许客户端查看服务器的性能。

PUT: 从客户端向服务器传送的数据取代指定的文档的内容。

DELETE:请求服务器删除指定的页面。

TRACE:回显服务器收到的请求,主要用于测试或诊断。

CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

(2)HTTP1.1新增的五种请求的基本方法和产生的请求结果 

 

PUT请求:与GET从服务器读取资源相反,PUT方法会向服务器写入资源. 有些发布系统允许用户创建Web页面,并用PUT直接向其传输到Web服务器中,如下图所示

PUT方法的语义就是让服务器用请求的主体部分来创建一个由所请求的URL命名的新文档,如果那个URL已经存在的话,就用这个资源来替代它. 例如, 在上图的请求中会在www.devtf.cn的网站根目录下创建一个new-art.txt的文件,文件内容为”This is file content”。

DELETE请求:顾名思义,DELETE方法所做的事情就是请服务器删除请求URL所指定的资源. 但是,客户端应用程序无法保证删除操作一定会被执行. 因为,HTTP规范允许服务器在不通知客户端的情况下撤销请求. 下图显示了一个DELETE方法实例

DELETE方式与GET请求一样,参数都需要放在请求的URL中。

 

TRACE请求:客户端发起一个请求时,这个请求可能要穿过防火墙,代理,网关或其他一些应用程序. 每个中间节点都可能会修改原始的HTTP请求. TRACE方法允许客户端在最终将请求发送给服务器时,看看他变成了什么样子. 
TRACE请求会在目的服务器端发起一个”环回”诊断. 行程最后一站的服务器会弹回一条TRACE响应,并在响应主体中携带它收到的原始请求报文. 这样客户端就可以查看在所有中间HTTP应用程序组成的请求/响应链上,原始报文是否以及如何被毁坏或修改过,如下图所示

    TRACE方法主要用于诊断,也就是说,用于验证请求是否如愿穿过了请求/响应链. 它也是一种很好的工具,可以用来查看代理和其他应用程序对用户请求所产生效果。

 

OPTIONS请求:OPTIONS方法请求Web服务器告知其支持的各种功能. 可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法(有些服务器可能只支持对一些特殊类型的对象使用特定的操作). 这对客户端应用程序提供了一种手段,使其不用实际访问那些资源就能判定访问各种资源的最优方式. 下图显示了一个使用OPTIONS方法的请求,如下图

1.2 HTTP的状态码

HTTP状态码的分类

(1)HTTP状态码的规范

    HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码。它由 RFC 2616 规范定义的,并得到RFC 2518、RFC 2817、RFC 2295、RFC 2774、RFC 4918等规范扩展。

(2)HTTP状态码的作用

    http状态码的核心作用是Web Server服务器用来告诉客户端,当前的网页请求发生了什么事,或者说当前Web服务器的响应状态。所以HTTP状态码常用来判断和分析当前Web服务器的运行状况。
(3)常见的HTTP状态码

200 OK 服务器成功处理了请求(这个是我们见到最多的);
301/302 Moved Permanently(重定向)请求的URL已移走。Response中应该包含一个Location URL, 说明资源现在所处的位置;
404 Not Found(页面丢失)未找到资源;

501 Internal Server Error服务器遇到一个错误,使其无法对请求提供服务。

 

HTTP状态码的含义

(1)HTTP状态码2**,3**,4**,5** 代表的含义

1开头:(被接受,需要继续处理。)
这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。

2开头 (请求成功)
这一类型的状态码,代表请求已成功被服务器接收、理解、并接受

3开头 (请求被重定向)
这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。

4开头:(请求错误)
这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。除非响应的是一个 HEAD 请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

5开头:(服务器错误)
这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。除非这是一个HEAD 请求,否则服务器应当包含一个解释当前错误状态以及这个状况是临时的还是永久的解释信息实体。浏览器应当向用户展示任何在当前响应中被包含的实体。

(2)获取HTTP状态码的方法

1.浏览器的F12调试(或者右键检查),network查看Status,如下图所示,status就是http返回的状态码;

2.各种在线输入网址查询HTTP状态的工具;

3.计算机语言,如python、java等。

1.3 HTTP协议响应头信息

HTTP响应头的含义

HTTP消息头是在,客户端请求(Request)或服务器响应(Response)时传递的,位请求或响应的第一行,HTTP消息体(请求或响应的内容)是其后传输。HTTP消息头,以明文的字符串格式传送,是以冒号分隔的键/值对,如:Accept-Charset: utf-8,每一个消息头最后以回车符(CR)和换行符(LF)结尾。HTTP消息头结束后,会用一个空白的字段来标识,这样就会出现两个连续的CR-LF。

(1)常见的HTTP响应头

响应头说明示例状态
Access-Control-Allow-Origin指定哪些网站可以跨域源资源共享Access-Control-Allow-Origin: *临时
Accept-Patch指定服务器所支持的文档补丁格式Accept-Patch: text/example;charset=utf-8固定
Accept-Ranges服务器所支持的内容范围Accept-Ranges: bytes固定
Age响应对象在代理缓存中存在的时间,以秒为单位Age: 12固定
Allow对于特定资源的有效动作;Allow: GET, HEAD固定
Cache-Control通知从服务器到客户端内的所有缓存机制,表示它们是否可以缓存这个对象及缓存有效时间。其单位为秒Cache-Control: max-age=3600固定
Connection针对该连接所预期的选项Connection: close固定
Content-Disposition对已知MIME类型资源的描述,浏览器可以根据这个响应头决定是对返回资源的动作,如:将其下载或是打开。Content-Disposition: attachment; filename="fname.ext"固定
Content-Encoding响应资源所使用的编码类型。Content-Encoding: gzip固定
Content-Language响就内容所使用的语言Content-Language: zh-cn固定
Content-Length响应消息体的长度,用8进制字节表示Content-Length: 348固定
Content-Location所返回的数据的一个候选位置Content-Location: /index.htm固定
Content-MD5响应内容的二进制 MD5 散列值,以 Base64 方式编码Content-MD5: IDK0iSsgSW50ZWd0DiJUi==已淘汰
Content-Range如果是响应部分消息,表示属于完整消息的哪个部分Content-Range: bytes 21010-47021/47022固定
Content-Type当前内容的MIME类型Content-Type: text/html; charset=utf-8固定
Date此条消息被发送时的日期和时间(以RFC 7231中定义的"HTTP日期"格式来表示)Date: Tue, 15 Nov 1994 08:12:31 GMT固定
ETag对于某个资源的某个特定版本的一个标识符,通常是一个 消息散列ETag: "737060cd8c284d8af7ad3082f209582d"固定
Expires指定一个日期/时间,超过该时间则认为此回应已经过期Expires: Thu, 01 Dec 1994 16:00:00 GMT固定: 标准
Last-Modified所请求的对象的最后修改日期(按照 RFC 7231 中定义的“超文本传输协议日期”格式来表示)Last-Modified: Dec, 26 Dec 2015 17:30:00 GMT固定
Link用来表示与另一个资源之间的类型关系,此类型关系是在RFC 5988中定义Link: ; rel="alternate"固定
Location用于在进行重定向,或在创建了某个新资源时使用。Location: http://www.itbilu.com/nodejs固定
P3PP3P策略相关设置P3P: CP="This is not a P3P policy!固定
Pragma与具体的实现相关,这些响应头可能在请求/回应链中的不同时候产生不同的效果Pragma: no-cache固定
Proxy-Authenticate要求在访问代理时提供身份认证信息。Proxy-Authenticate: Basic固定
Public-Key-Pins用于防止中间攻击,声明网站认证中传输层安全协议的证书散列值Public-Key-Pins: max-age=2592000; pin-sha256="……";固定
Refresh用于重定向,或者当一个新的资源被创建时。默认会在5秒后刷新重定向。Refresh: 5; url=http://itbilu.com 
Retry-After如果某个实体临时不可用,那么此协议头用于告知客户端稍后重试。其值可以是一个特定的时间段(以秒为单位)或一个超文本传输协议日期。
  • 示例1:Retry-After: 120
  • 示例2: Retry-After: Dec, 26 Dec 2015 17:30:00 GMT

固定

Server服务器的名称Server: nginx/1.6.3固定
Set-Cookie设置HTTP cookieSet-Cookie: UserID=itbilu; Max-Age=3600; Version=1固定: 标准
Status通用网关接口的响应头字段,用来说明当前HTTP连接的响应状态。Status: 200 OK 
TrailerTrailer用户说明传输中分块编码的编码信息Trailer: Max-Forwards固定
Transfer-Encoding用表示实体传输给用户的编码形式。包括:chunkedcompress、 deflategzipidentityTransfer-Encoding: chunked固定
Upgrade要求客户端升级到另一个高版本协议。Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11固定
Vary告知下游的代理服务器,应当如何对以后的请求协议头进行匹配,以决定是否可使用已缓存的响应内容而不是重新从原服务器请求新的内容。Vary: *固定
Via告知代理服务器的客户端,当前响应是通过什么途径发送的。Via: 1.0 fred, 1.1 itbilu.com (nginx/1.6.3)固定
Warning一般性警告,告知在实体内容体中可能存在错误。Warning: 199 Miscellaneous warning固定
WWW-Authenticate表示在请求获取这个实体时应当使用的认证模式。WWW-Authenticate: Basic固定


(2)HTTP响应头的作用

相应的响应头用来描述服务器回给你对所返回的content的一些一些描述,服务器类型信息,编码类型,内容长度等等呢个。

 

HTTP响应头的格式

HTTP应答与HTTP请求相似,HTTP响应也由3个部分构成,分别是:

  1. 状态行
  2. 响应头(Response Header)
  3. 响应正文

在接收和解释请求消息后,服务器会返回一个HTTP响应消息。 
状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。 
格式: HTTP-Version Status-Code Reason-Phrase CRLF 
例如: HTTP/1.1 200 OK \r\n

状态代码:状态代码由3位数字组成,表示请求是否被理解或被满足。 
状态描述:状态描述给出了关于状态代码的简短的文字描述。

响应头可能包括: 

Location:Location响应报头域用于重定向接受者到一个新的位置。例如:客户端所请求的页面已不存在原先的位置,为了让客户端重定向到这个页面新的位置,服务器端可以发回Location响应报头后使用重定向语句,让客户端去访问新的域名所对应的服务器上的资源。当我们在JSP中使用重定向语句的时候,服务器端向客户端发回的响应报头中,就会有Location响应报头域。 
Server:Server响应报头域包含了服务器用来处理请求的软件信息。它和User-Agent请求报头域是相对应的,前者发送服务器端软件的信息,后者发送客户端软件(浏览器)和操作系统的信息。下面是Server响应报头域的一个例子:Server: Apache-Coyote/1.1 
WWW-Authenticate:WWW-Authenticate响应报头域必须被包含在401(未授权的)响应消息中,这个报头域和前面讲到的Authorization请求报头域是相关的,当客户端收到401响应消息,就要决定是否请求服务器对其进行验证。如果要求服务器对其进行验证,就可以发送一个包含了 Authorization报头域的请求,下面是WWW-Authenticate响应报头域的一个例子:WWW-Authenticate: Basic realm="Basic Auth Test!" 
从这个响应报头域,可以知道服务器端对我们所请求的资源采用的是基本验证机制。 
Content-Encoding:Content-Encoding实体报头域被使用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容编码,因而要获得Content- Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding主要用语记录文档的压缩方法,下面是它的一个例子: Content-Encoding: gzip。如果一个实体正文采用了编码方式存储,在使用之前就必须进行解码。 
Content-Language:Content-Language实体报头域描述了资源所用的自然语言。Content-Language允许用户遵照自身的首选语言来识别和区分实体。如果这个实体内容仅仅打算提供给丹麦的阅读者,那么可以按照如下的方式设置这个实体报头域:Content-Language: da。 
如果没有指定Content-Language报头域,那么实体内容将提供给所以语言的阅读者。 
Content-Length: Content-Length实体报头域用于指明正文的长度,以字节方式存储的十进制数字来表示,也就是一个数字字符占一个字节,用其对应的ASCII码存储传输。 
Content-Type 
Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型。例如:

Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=GB2312
  • 1
  • 2

Last-Modified:Last-Modified实体报头域用于指示资源最后的修改日期及时间。 
Expires 
Expires实体报头域给出响应过期的日期和时间。通常,代理服务器或浏览器会缓存一些页面。当用户再次访问这些页面时,直接从缓存中加载并显示给用户,这样缩短了响应的时间,减少服务器的负载。为了让代理服务器或浏览器在一段时间后更新页面,我们可以使用Expires实体报头域指定页面过期的时间。当用户又一次访问页面时,如果Expires报头域给出的日期和时间比Date普通报头域给出的日期和时间要早(或相同),那么代理服务器或浏览器就不会再使用缓存的页面而是从服务器上请求更新的页面。不过要注意,即使页面过期了,也并不意味着服务器上的原始资源在此时间之前或之后发生了改变。 
Expires实体报头域使用的日期和时间必须是RFC 1123中的日期格式,例如:

Expires: Thu, 15 Sep 2005 16:00:00 GMT
  • 1

HTTP1.1的客户端和缓存必须将其他非法的日期格式(也包括0)看作已过期。例如,为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置它的值为0,如下(JSP):response.setDateHeader("Expires",0);

下面是一个HTTP响应的例子:

HTTP/1.1 200 OK

Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112

 

1.4 HTTP协议中的URL

URL的基本构成

(1)URL的基本概念

    统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。


(2)URL的基本结构

    基本URL包含模式(或称协议)、服务器名称(或IP地址)、路径和文件名,如“协议://授权/路径?查询”。完整的、带有授权部分的普通统一资源标志符语法看上去如下:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志

模式/协议(scheme):它告诉浏览器如何处理将要打开的文件。最常用的模式是超文本传输协议(Hypertext Transfer Protocol,缩写为HTTP),这个协议可以用来访问网络。其他协议如下:
http——超文本传输协议资源
https——用安全套接字层传送的超文本传输协议
ftp——文件传输协议
mailto——电子邮件地址
ldap——轻型目录访问协议搜索
file——当地电脑或网上分享的文件
news——Usenet新闻组
gopher——Gopher协议
telnet——Telnet协议

    文件所在的服务器的名称或IP地址,后面是到达这个文件的路径和文件本身的名称。服务器的名称或IP地址后面有时还跟一个冒号和一个端口号。它也可以包含接触服务器必须的用户名称和密码。路径部分包含等级结构的路径定义,一般来说不同部分之间以斜线(/)分隔。询问部分一般用来传送对服务器上的数据库进行动态询问时所需要的参数。
有时候,URL以斜杠“/”结尾,而没有给出文件名,在这种情况下,URL引用路径中最后一个目录中的默认文件(通常对应于主页),这个文件常常被称为 index.html 或 default.htm。


(3)URL编码格式

URL编码遵循下列规则: 每对name/value由&;符分开;每对来自表单的name/value由=符分开。如果用户没有输入值给这个name,那么这个name还是出现,只是无值。任何特殊的字符(就是那些不是简单的七位ASCII,如汉字)将以百分符%用十六进制编码,当然也包括象 =,&;,和 % 这些特殊的字符。其实url编码就是一个字符ascii码的十六进制。不过稍微有些变动,需要在前面加上“%”。比如“\”,它的ascii码是92,92的十六进制是5c,所以“\”的url编码就是%5c。那么汉字的url编码呢?很简单,看例子:“胡”的ascii码是-17670,十六进制是BAFA,url编码是“%BA%FA”。

 

  • 6
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
HTTP 协议(Hypertext Transfer Protocol)是一种用于传输超文本的应用层协议,是万维网数据传输的基础。它采用客户端-服务器模式,客户端发起请求,服务器返回响应。下面对 HTTP 协议进行详细解析。 HTTP 协议以简洁的请求-响应模型为基础。客户端发送请求报文给服务器,报文包含请求方法、URL、协议版本等信息。服务器收到请求后,根据请求内容进行相应处理,并返回响应报文给客户端。响应报文包含协议版本、状态码、响应头和响应体等信息。客户端接收到响应后,根据状态码判断请求是否成功,并解析响应内容。 HTTP 协议的特点主要包括:无状态、可靠性差、传输效率低。无状态指的是服务器不会保存任何客户端的状态信息,每次请求都是单独的。可靠性差是因为 HTTP 使用 TCP 进行数据传输,TCP 协议本身也有一定的不可靠性。传输效率低是由于 HTTP 建立连接的开销较大,并且每次请求都需要重新建立连接。 HTTP 协议的工作流程如下:客户端发送一条请求到服务器,服务器接收并解析请求,处理请求并生成响应,将响应发送给客户端,客户端接收并解析响应。 HTTP 协议的主要优点包括:易于使用、灵活性强、便于扩展。易于使用指的是 HTTP 的语法规则简单明了,易于理解和实现。灵活性强指的是可以通过设置请求头、传递参数等方式来定制请求。便于扩展指的是可以根据需要添加新的功能或特性。 总之,HTTP 协议作为互联网应用最常用的协议之一,它的设计简洁、易于使用,为用户提供了方便、快速的网络通信方式。同时,由于协议本身的一些限制,HTTP 协议的传输效率相对较低,因此在一些对效率要求较高的场景下,可能需要使用其他协议替代。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

devi1.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值