前端浏览器及网络面试考点

本文详细介绍了HTTP协议的特点,包括无连接和无状态特性,以及报文结构。重点讲解了跨域的解决方案,如JSONP、CORS、nginx代理和WebSocket。此外,探讨了回流和重绘、DOM渲染、点击劫持和XSS防护策略。同时,阐述了TCP的三次握手和四次挥手过程,以及状态码的含义。最后,对比了cookie、session、localStorage和sessionStorage的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http协议

特点:

  • 支持客户/服务器模式。
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。为了解决这个问题, Web程序引入了Cookie机制来维护状态。

报文结构图在这里插入图片描述

跨域方式有哪些?他们的特点是什么

1.JSONP

  • JSONP通过同源策略涉及不到的"漏洞",也就是像img中的src,link标签的href,script的src都没有被同源策略限制到
  • JSONP只能通过get请求
  • 原理
function addScript(src){
	var scriptEl=document.createElement('script')
	scriptEl.setAttribute('type','text/javascript')
	scriptEl.src=src
	document.appendChild(scriptEl)
}
//使用回调获取数据
function endFn(res){
	console.log(res.message)
}
// 前后端商量好,后端如果传数据的话,返回`endFn({message:'hello'})`

2.CORS

  • CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否
  • 有简单请求和非简单请求
  • 满足以下条件,就是简单请求
    • 请求方法是HEAD、POST、GET
    • 请求头只有Accept、AcceptLanguage、ContentType、ContentLanguage、Last-Event-Id
  • 简单请求,浏览器自动添加一个Origin字段
    • 同时后端需要设置的请求头
      • Access-Control-Allow-Origin --必须 指定授权访问的域
      • Access-Control-Expose-Headers
      • Access-Control-Allow-Methods:授权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)
    • Access-Control-Allow-Credentials --是否可传cookie
    • 要是想传cookie,前端需要设置xhr.withCredentials = true,后端设置Access-Control-Allow-Credentials
  • 非简单请求,浏览器判断是否为简单请求,如果是非简单请求,则 浏览器先发送一个header头为option的请求进行预检
    • 预检请求格式(请求行 的请求方法为OPTIONS(专门用来询问的))
      • Origin
      • Access-Control-Request-Method
      • Access-Control-Request-Header
    • 浏览器检查了Origin、Access-Control-Allow-Method和Access-Control-Request-Header之后确认允许就可以做出回应了
    • 通过预检后,浏览器接下来的每次请求就类似于简单请求了

3.ngnix

4.proxy

在vue.config.js中
在这里插入图片描述
在这里插入图片描述

defer和async

  • 首先在一般情况下,script标签是会阻塞DOM解析的,从而我们尽量不要把script放在head中,应该尽量把它放在body最下面
  • defer和async都是异步加载js代码
  • defer
    • 给script标签加上defer,其就不会阻塞dom的解析了,等待dom渲染完之后才会运行js代码,如果是多个script标签添加defer,那么按照顺序同步执行,其是在DOMContentLoaded之前运行的
  • async
    • 给script加上async属性之后,不会阻塞dom解析,但是会进行异步加载,当下载完毕就立即执行,多个async属性标签是没有执行顺序的,谁先下载完就谁先执行
    • 如果 script 标签没有操作任何 dom 信息,且不彼此依赖的话,可以使用 async

nginx代理跨域

  • nginx模拟一个虚拟服务器,因为服务器与服务器之间是不存在跨域的,
  • 发送数据时 ,客户端->nginx->服务端
  • 返回数据时,服务端->nginx->客户端

websocket

回流和重绘

  • 回流
    • 当我操作Dom时,其结构会发生改变,从而影响整体布局,这个过程就会发生重绘
    • 当元素width、height、margin、padding、left、top发生改变时会发生回流
    • 使用DOM节点增减或移动
    • 读写offset、client、scroll时,浏览器为获取这些值,会进行回流操作
    • 使用window.getComputedStyle
      • getComputedStyle 返回的对象是 CSSStyleDeclaration 类型的对象,包括了内联样式、嵌入样式和外部样式。取数据的时候可以直接按照属性的取法去取数据,例如 style.backgroundColor
  • 重绘
    • 当改变元素时,只改变了它的外观,比如背景颜色,没有影响到其他布局,这时会发生重绘
    • 回流必将引起重绘,重绘不一定发生回流
  • 如何避免和减少
    • 尽量避免频繁使用style,而是使用修改class的方式
    • 对于 resize 和 scroll 进行防抖节流处理
    • 使用createDocumentFragment
      var ul = document.getElementById("ul");
      var fragment = document.createDocumentFragment();
      for (var i = 0; i < 20; i++) {
         var li = document.createElement("li");
         li.innerHTML = "index: " + i;
         fragment.appendChild(li);
      }
      ul.appendChild(fragment);
      

从浏览器输入url后都经历了什么?

  1. 先进行DNS域名解析,首先查看本地host文件,若没有找到在本地域名服务器去查找若还没找到从根域名服务器查找,根域名服务器会告诉你在哪个服务器查找,最后查找到对应ip地址,并把对应规则保存在本地的hosts文件文中方便下次寻找。
  2. 进行http请求,三次挥手建立TCP连接
  3. HTTP发起请求
  4. 服务器处理请求,浏览器接收HTTP响应
  5. 客户端自上而下执行代码
    • 遇到css加载时,css不会阻塞DOM树的解析,但会阻塞DOM树的渲染,并且CSS会阻塞下面js的执行
    • js加载会影响DOM的解析,是因为js可能会进行dom操作,先解析侯家庄的化,DOM树还得重写解析,性能较差,如果不想阻塞DOM树,跨域给script添加defer或async标签
      • defer:不会阻塞DOM树解析,等Dom解析完之后才会运行,在DOMContentload之前
      • async:不会阻塞DOM树解析,等该资源下载完之后立即执行,这时需要确保其中不会造成浏览器渲染回流的操作,否则会降低性能
    • 进行Dom渲染和Render树渲染
      • 获取html并解析为Dom树
      • 获取Css并解析为cssom(Css树)
      • 把cssom和Dom合并成渲染树(render)
      • 进行布局
      • 进行绘制
      • 回流重绘

点击劫持

  • 点击劫持是指利用 iframe+css 的 opacity 把危险网址设置为透明覆盖到安全的网址上面,使用户误以为在安全网址下操作。
  • 防范:
    • 在 http 中配置 X-frame-options 设置为 deny 可以禁止被 iframe 嵌入

XSS 脚本注入

  • 指恶意攻击者通过Web页面插入恶意代码,当用户浏览该页时,嵌入该Web里的Script代码会被执行,从而达到恶意攻击用户的目的
  • xxs漏洞通常时通过php的输出函数将javascript代码输出到页面中,通过用户本地浏览执行,从而xss漏洞的关键就是寻找参数未过滤的输出函数。常见的输出函数有: echo printf print print_r sprintf die var-dump var_export.
  • 防御
    • 使用转义函数htmlentities()(),htmlspecialchars(),对用户输入的<>进行转义

csrf 攻击原理 (Cross site request forgery)跨站请求伪造

介绍:当用户登录了网页A,但没有退出登录时,打开了危险的网页B,网页B可以带着网页A的cookie向网页A的服务器发送请求,让服务器认为这个是可信任用户,从而达到了攻击的目的。
过程:

  1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
  2. 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
  3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
  4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A(在 B 页中可以使用一个隐藏的 iframe 来向 A 页发起请求,只要用户没有登出 A 网站,临时 cookie 一直保存在内存中)
  5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
    防御:使用token来进行身份验证

cookie和token验证身份

cookie:
1.用户输入登陆凭据;
2。服务器验证凭据是否正确,并创建会话,然后把会话数据存储在数据库中;
3.具有会话id的cookie被放置在用户浏览器中;
4.在后续请求中,服务器会根据数据库验证会话id,如果验证通过,则继续处理;
5.一旦用户登出,服务端和客户端同时销毁该会话。
在这里插入图片描述

token:
1.用户使用账号和密码登录
2.服务端验证通过,使用JWT生成数token,并把token返回给客户端
3.客户端把token存放在localstorage或cookie中
4。后续请求时,在请求头在Authorization上添加token,服务端通过JWT进行解密,验证用户身份,验证通过,继续处理。
5.当用户退出客户存放的token将被删除
在这里插入图片描述

token验证相对于cookie验证的优势

无状态
基于token的验证是无状态的,这也许是它相对cookie来说最大的优点。后端服务不需要记录token。每个令牌都是独立的,包括检查其有效性所需的所有数据,并通过声明传达用户信息。
服务器唯一的工作就是在成功的登陆请求上签署token,并验证传入的token是否有效。

防跨站请求伪造(CSRF)
举个CSRF攻击的例子,在网页中有这样的一个链接
假设你已经通过银行的验证并且cookie中存在验证信息,同时银行网站没有CSRF保护。一旦用户点了这个图片,就很有可能从银行向tom这个人转1000块钱。
但是如果银行网站使用了token作为验证手段,攻击者将无法通过上面的链接转走你的钱。(因为攻击者无法获取正确的token)
多站点使用
cookie绑定到单个域。foo.com域产生的cookie无法被bar.com域读取。使用token就没有这样的问题。这对于需要向多个服务获取授权的单页面应用程序尤其有用。
使用token,使得用从myapp.com获取的授权向myservice1.com和myservice2.com获取服务成为可能。
支持移动平台
好的API可以同时支持浏览器,iOS和Android等移动平台。然而,在移动平台上,cookie是不被支持的。
性能
一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算的Token验证和解析要费时得多。
参考

https://www.jianshu.com/p/ce9802589143

TCP的三次握手四次挥手

转自:

https://blog.youkuaiyun.com/qq_38950316/article/details/81087809

在这里插入图片描述

三次握手:
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。此时服务器为收听状态

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;这时服务端只知道可以接收到客户端的报文,到不知道客户端是否可以接收到服务端的报文。

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

在这里插入图片描述

四次挥手过程理解:

  1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
    在这里插入图片描述

常见问题:
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

   现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

参考:

https://www.bilibili.com/video/BV1bi4y1x7m5?from=search&seid=6892044775622095975&spm_id_from=333.337.0.0

说说你知道的状态码

  • 1xx表示信息
    • 100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
    • 101 Switching Protocols 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。
  • 2开头表示成功
    • 一般都是200
  • 3开头表示重定向
    • 301永久重定向:输入A网站跳转到B网站。用途,
    • 302临时重定向
    • 304表示可以在缓存中取数据(协商缓存)
    • 参考: https://ys720.com/jiaocheng/qita/1799.html

  • 4开头表示客户端错误
    • 400 Bad Request 服务器未能理解请求。
    • 401 Unauthorized 被请求的页面需要用户名和密码。
    • 402 Payment Required 此代码尚无法使用。
    • 403 Forbidden 对被请求页面的访问被禁止。
    • 404 Not Found 服务器无法找到被请求的页面。
  • 5开头表示服务端错误
    -500 Internal Server Error 请求未完成。服务器遇到不可预知的情况。
    • 501 Not Implemented 请求未完成。服务器不支持所请求的功能。
    • 502 Bad Gateway 请求未完成。服务器从上游服务器收到一个无效的响应。
    • 503 Service Unavailable 请求未完成。服务器临时过载或当机。
    • 504 Gateway Timeout 网关超时。
    • 505 HTTP Version Not Supported 服务器不支持请求中指明的HTTP协议版本。

参考

网络模型有哪些

OSI七层模型:

  • 物理层: 将数据转换为可通过物理介质传送的电子信号 相当于邮局中的搬运工人。
    • 物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。
  • 数据链路层: 决定访问网络介质的方式。
    • 数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧
      在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址,相当于邮局中的装拆箱工人。
  • 网络层: 使用权数据路由经过大型网络 相当于邮局中的排序工人。
  • 传输层: 提供终端到终端的可靠连接 相当于公司中跑邮局的送信职员。
  • 会话层: 允许用户使用简单易记的名称建立连接 相当于公司中收寄信、写信封与拆信封的秘书。
  • 表示层: 协商数据交换格式 相当公司中简报老板、替老板写信的助理。
  • 应用层: 用户的应用程序和网络之间的接口。
    在这里插入图片描述
    在这里插入图片描述

cookie session localStorage sessionStorage差异

  • cookie
    • cookie的内容主要包括:名字、值、过期时间、路径和域。路径与域一起构成cookie的作用范围。若不设置时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就会消失。这种生命期为浏览器会话期的cookie被称为会话cookie。
      会话cookie一般不存储在硬盘而是保存在内存里,当然这个行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再打开浏览器这些cookie仍然有效直到超过设定的过期时间。对于保存在内存里的cookie,不同的浏览器有不同的处理方式session机制。
    • 应用:用于存储基本信息
  • session
    • 介绍:当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
    • 应用:用于存储重要信息
  • cookie 和 session 的区别
    1、cookie数据存放在客户的浏览器上,session数据放在服务器上
    2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
    3、session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie
    4、单个cookie保存的数
    据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie
    5、建议将登录信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中
    6、session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知道其中的信息
    7、session中保存的是对象,cookie中保存的是字符串
    8、session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的。
    9、COOKIE:是服务端向客户端写入的小的片段信息。cookie信息保存在服务器缓存区,不会在客户端显现。当你第一次登陆一个网站,服务器向你的机器写得片段信息。你可以在Internet选项中找到存放cookie的文件夹。如果不删除,cookie就一直在这个文件夹中。
    10、session需要借助cookie才能正常工作。如果客户端完全禁止cookie,session将失效。 但是如果服务器端启用了url编码,也就是用 URLEncoder.encode()把所有的url编码了,则会在url后面出现如下类似的东西 index.jsp:jsessionid=fdsaffjdlks;jaf;lkdjsf 服务器通过这个进行session的判断.
    11.Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等,而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。仅运用Cookie或者仅运用Session可能完成不了理想的效果。这时应该尝试一下同时运用Cookie与Session。Cookie与Session的搭配运用在实践项目中会完成很多意想不到的效果。
  • sessionStorage、localStorage和cookie区别
    共同点:都是保存在浏览器端、且同源的
    区别:
    1、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
    2、存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
    3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效,页面刷新值还是存在;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
    4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面,页面刷新值还是存在;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
    5、web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
    6、web Storage的api接口使用更方便

参考 https://www.cnblogs.com/jing-tian/p/10991431.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值