Cookie、Session、Token、JWT

Cookie、Session、Token、JWT

前言:

  • 最近重温接口测试,对cookie、session、token、jwt感到疑惑,在这里进行梳理,加深理解,也感谢csdn各位大佬的分享,东看看西搬搬,这里汇总下我了解到的内容
    转载-原文链接:
    https://blog.csdn.net/weixin_35681869/article/details/107096474
    https://www.cnblogs.com/xiaolixun/p/8716232.html
    https://zhuanlan.zhihu.com/p/100460817
    https://blog.csdn.net/weixin_42170152/article/details/103738139
    https://blog.csdn.net/AwayFuture/article/details/102753627
    https://blog.csdn.net/qq_37939251/article/details/83511451
    http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html --by 阮一峰
    https://www.jianshu.com/p/bbba6b337c7e

几个概念

  • 什么是认证(Authentication)

    • 认证用户身份,证明“你是你”,互联网中的认证
      • 人脸识别登录
      • 账密登录
      • 验证码登录
  • 什么是授权(Authorization)

    • 用户授予第三方应用访问某些资源的权限
      • 比如:登录app会弹出询问是否允许app获取相关权限(访问相册、地理位置)
      • 实现授权的方式有:cookie、session、token、OAuth
  • 什么是凭证(Credentials)

    • 实现认证授权的前提,一种证书,用于证明身份的媒介
      • 可以认为是你的身份证
      • 证明你学历的 毕业证和学位证

Cookie、Session产生的原因

  • 早起互联网世界只有文字的获取,HTTP本身是无状态协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息):
    • 每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。
    • 所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。

Cookie

什么是Cookie

  • cookie是保存在客户端的纯文本文件,如txt,也可以说是一门客户端缓存技术,用于保存客户端请求信息

Cookie的产生

1、cookie是由服务器产生,当浏览器第一次访问服务器,且服务器有Session方法,服务器此时并不知道他的身份,所以就会创建一个独特的身份标识数据,格式:key:value,以及服务端调用Session对象生成的JsessionId放入到set-Cookie字段里,随着响应报文发送给浏览器,
2、浏览器看到有set-Cookie 字段以后,就知道这是服务器给的身份标识,于是就保存起来,下次请求时自动将这个 key=value值放入到Cookie字段中发给服务端
3、服务端收到请求报文后,发现Cookie字段中有值,就能根据此值去寻找Session对象,识别该用户的身份,然后提供个性化的服务
在这里插入图片描述

Cookie重要属性

序号属性说明
1name:value键值对,设置 Cookie 的名称及相对应的值,都必须是字符串类型 - 如果值为 Unicode 字符,需要为字符编码。- 如果值为二进制数据,则需要使用 BASE64 编码。
2domain指定 cookie 所属域名,默认是当前域名
3path指定 cookie 在哪个路径(路由)下生效,默认是 ‘/’。如果设置为/abc,则只有 /abc 下的路由可以访问到该 cookie,如:/abc/read。
4maxAgecookie 失效的时间,单位秒。如果为整数,则该 cookie 在 maxAge 秒后失效。如果为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 cookie 。默认为 -1。- 比 expires 好用。
5expires过期时间,在设置的某个时间点后该 cookie 就会失效。一般浏览器的 cookie 都是默认储存的,当关闭浏览器结束这个会话的时候,这个 cookie 也就会被删除
6secure该 cookie 是否仅被使用安全协议传输。安全协议有 HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
7httpOnly如果给某个 cookie 设置了 httpOnly 属性,则无法通过 JS 脚本 读取到该 cookie 的信息,但还是能通过 Application 中手动修改 cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全
说明:XSS,跨站脚本攻击。攻击者获得页面的js权限,能操作页面的一切,包括Session Storage和未设置HTTP Only属性的Cookie

Cookie 特点汇总

cookie数据由服务器生成,发送给浏览器保存
cookie数据类型只能是字符串
cookie数据的格式:键值对
cookie数据过期机制:设置expire值
cookie是一门客户端技术,一般是由服务器生成返回给浏览器客户端来保存的,并且cookie是
以键值对的形式保存在浏览器客户端的,每一个cookie都会有name,value,domain,path,过期时间...。
cookie有很多使用场景,在项目中比较常见的有:
1.登录记住用户名
2.记录用户浏览记录
...

上面应用中大家最熟悉的应该就是记住用户名这个场景了,以京东网站的登录功能为例,当我
们登录了一次京东,后面再去登录页面登录的时候,会发现它会帮你回填之前的用户名,这个
场景就是通过cookie技术实现的。
拓展:cookie是有过期机制的,可以通过设置cookie的过期时间来控制cookie什么时候过期,
这个mp的过期时间为一个月,因此这一个月内只要不清除浏览器端的cookie数据,那么使用火
狐浏览器来访问京东的登录页面都可以看到手机号回填的效果。

Cookie的作用

  • 存储会话信息,跟踪会话状态,联系浏览器和服务器

Cookie的优点

  • 存储会话信息,可以用于跟踪会话状态
  • 保存在浏览器,数据小,不会对服务器造成压力,提升了访问速度
  • 可以长时间持续,也可以短时间持续(基于过期时间的设置)cookie可长可短,session一般较短

使用Cookie需要考虑的问题

  • 客户端用户如果设置禁止 Cookie, 则 Cookie不能建立。

  • 因为存储在客户端,容易被客户端篡改,使用前需要验证合法性

  • 不要存储敏感数据,比如用户密码,账户余额,注意防止crsf攻击(cookie伪装)

      说明:CSRF,跨站请求伪造,就是钓鱼网站,在网站A,发送一个向网站B的请求,由于浏览器会在请求中加上此域的Cookie,
      所以如果在浏览器登录了网站B,又打开了钓鱼网站A,网站A构造的前往网站B的请求就会带上你的Cookie,
      如果Cookie中有用户凭证,服务器认为你是登录用户,请求就会被响应。比如点赞、关注、发色情广告等请求)
    
  • 使用 httpOnly 在一定程度上提高安全性

  • 尽量减少 cookie 的体积,单个 Cookie 保存的数据不能超过 4K,

  • 一个浏览器针对一个网站(其实就是一个domain)最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie

  • 设置正确的 domain 和 path,减少数据传输

  • cookie会被附加在每个HTTP请求中,所以无形中增加了流量

  • cookie 无法跨域, 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)

  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

Session

什么是Session

  • session是一门服务端会话缓存技术,用于存储一次会话的多次请求的数据

Session的产生

如下图,浏览器第一次请求,请求头中并未携带Cookie信息,上面我们也说,Cookie是由服务端生成,其实此时服务端调用HttpSession生成的Session对象(也可以认为session的产生更早于Cookie),它会产生一个JsessionId(名字可以自定义)随其他的key-value的信息一起写入到Set-Cookie,返回给浏览器,一般第一次请求和应答结束后JsessionId会自动失效,这是他的过期时间,一般它只存在于一次会话的开始和结束,我们往往也使用SessionId来跟踪记录会话时长

  • 如下图1,浏览器第一次请求:
    在这里插入图片描述
    在这里插入图片描述

  • 如下图2,浏览器第一次请求
    在这里插入图片描述
    在这里插入图片描述

  • 如下图,浏览器第二次请求
    对比jsessionid可看出,第一次请求后响应头的set-Cookie里的sessionid和 第二次请求是请求头里Cookie字段的sessionid是同一个,

在这里插入图片描述
在这里插入图片描述

  • 交互流程
    - 转载自 知乎(https://zhuanlan.zhihu.com/p/100460817)
    在这里插入图片描述

Session特点汇总

session的特点:
session由服务器端的web容器创建,保存在服务器端。
session保存数据:键值对形式
session可以是任何数据类型,任意数据大小
session过期:默认30分钟
session持久化:用于解决重启服务器后session就消失的问题。在数据库中存储session,而不是存储在内存中。通过包:express-mysql-session
session是服务端的会话技术,当用户登录了系统,服务器端的web容器就会创建一个会话,此会话中可以保存登录用户的信息,并且也是以键值对的形式去保存的,现在大部分系统都是使用的session技术来做的鉴权(权限鉴定),即:当用户登录完了才可以访问系统中的一些页
面和数据。
其它:当客户端存储的cookie失效后,服务端的session不会立即销毁,会有一个延时,服务端会定期清理无效session,不会造成无效数据占用存储空间的问题。
以下面的系统为例:
直接访问系统lmcanon的首页index.html无法访问成功,会被重定向到登录页login.html,因为这个系统有做用户鉴权,没有登录的用户无法访问系统里面的数据。

Session的产生总结

(转载自https://www.cnblogs.com/xiaolixun/p/8716232.html ):

  1. session生成大概是,首先你发个请求去服务端,如果你的cookie里面有他之前写的session(叫什么都ok,jsessionid或者其他都行,取决于容器的实现),那么直接读取容器内存该sessionid对应的信息
  2. 如果是第一次请求,分2种情况:
    1. 如果服务端调用获取或设置session的方法,但是传过来的cookie里面没有(根本没cookie可传过去),那么自动生成一个session,并在响应头里面加上Set-Cookie,向浏览器申请写入cookie
    2. 如果服务端没有调用获取或设置session的方法,那么就不会生成并下发session,应该是为了节省网络以及服务器资源。

session相关概念

  • sessionStorage:客户端用于存储变量的,仅在当前会话下有效,关闭页面或浏览器后被清除

  • localStorage:除非被清除,否则永久保存

Session的作用

  • 存储会话信息供浏览器后续请求使用,可以获取并修改变量的值。和cookie一起使用识别同一个客户。

Session的优点

  • 相比JWT,最大优势是可以主动清除session
  • session保存在服务器端相对安全。
  • 结合cookie使用,较为灵活,兼容性好

使用Session需要考虑的问题

  • 将 session 存储在服务器里面,当用户同时在线量比较多时,这些 session 会占据较多的内存,需要在服务端定期的去清理过期的 session

  • 查询session信息可能会有数据库查询操作,带来性能问题

  • 当网站采用集群部署的时候,会遇到多台 web 服务器之间如何做 session 共享的问题。因为 session 是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建 session 的服务器,那么该服务器就无法拿到之前已经放入到 session 中的登录凭证之类的信息了。

  • 当多个应用要共享 session 时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好 cookie 跨域的处理。

  • sessionId 是存储在 cookie 中的,假如浏览器禁止 cookie 或不支持 cookie 怎么办? 一般会把 sessionId 跟在 url 参数后面即重写 url,所以 session 不一定非得需要靠 cookie 实现

  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

对比Cookie和Session

联系

  1. 都可以保存用户信息
  2. session的使用要求浏览器支持cookie,如果浏览器不支持or禁止cookie,则session不能使用
  3. 用户访问时,服务器创建or查找session,生成sessionid并传给浏览器,浏览器将其保存在cookie中一并放入内存,也可认为cookie是session在浏览器的标识

区别

  1. 安全性:Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的(客户端的容易被拦截,伪装)。
  2. 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
  3. 有效期不同:Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
  4. 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
    5.保持状态的方案不同: cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。

Token

Token出现的背景

  1. 在早前的Web应用中,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议, 就是请求加响应, 尤其是我不用记住是谁刚刚发了HTTP请求,每个请求对我来说都是全新的;
2. 但是随着交互式Web应用的兴起,像在线购物网站,需要登录的网站等等,马上就面临一个问题,那就是要管理会话,必须记住哪些人登录系统, 哪些人往自己的购物车中放商品, 也就是说我必须把每个人区分开,这就是一个不小的挑战,因为HTTP请求是无状态的,所以想出的办法就是给大家发一个会话标识(session id), 说白了就是一个随机的字串,每个人收到的都不一样, 每次大家向我发起HTTP请求的时候,把这个字符串给一并捎过来, 这样我就能区分开谁是谁了;

3. 但是客户端只需要保存自身的session id,而服务器端则要保存所有客户端的session id ,这对服务器说是一个巨大的开销 , 严重的限制了服务器扩展能力;Token的出现解决了这个问题,因为服务端不需要存储Token的信息,而是通过CPU的计算 + 数据的加密解密再核对Token的方式来验证用户是否合法(即HTTP请求信息有没有被篡改),让服务器内存得到释放;

4. session id可以被伪造,没有采取加密的方法!!!,一旦攻击者通过session id伪造攻击,就会给服务器带来压力甚至击垮服务器。

5. Token是通过加密算法(如:HMAC-SHA256算法)来实现session对象验证的,这样使得攻击者无法伪造token来达到攻击或者其他对服务器不利的行为。

什么是Token(令牌)

token是服务端生成的一串字符串,以作客户端进行请求的令牌,访问资源接口(API)时所需要的资源凭证(身份证),当第一次登陆后,服务器生成一个token便将此token返回给客户端,以后客户端只要带上这个token前来请求数据即可,无需再次带上用户名和密码

Token的产生

  • 原料:浏览器提供的登录信息:账密等用户信息
  • 处理器:服务器
  • 处理手段:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)登录信息做数字签名(哈希算法)
  • 使用流程:
    • 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。流程是这样的:
    1. 客户端使用用户名跟密码请求登录
    2. 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端 客户端收到 Token
    3. 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
    4. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token 服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据
    5. APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为token,存储到服务器中,并返回token到APP,以后APP请求时,
    6. 凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让他重新登录。其中服务器上token设置一个有效期,每次APP请求的时候都验证token和有效期。

在这里插入图片描述

Token的特点

1、是由服务端校验客户端传输的账密成功后签发的一串字符串,发给了客户端,服务端可以缓存起来(因为token可以刷新)
2、保存在客户端的token自己保留有大量信息,服务器没有存储这些信息。

Token的作用

  1. 用来作身份验证
  2. 节省服务器内存
  3. 数据签名防伪造攻击

Token的优点

  1. 服务端无状态化、可扩展性好

    • 在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成 一些拥堵。但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。
  2. 支持移动端设备

    • Tokens能够创建与其它程序共享权限的程序。当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理)
      这时采用Token认证机制就会简单得多。
  3. 安全

    • 请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。
  4. 支持跨域访问

    • 我们提前先来谈论一下CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。而Cookie是不允许垮域访问的(垮域访问:两个域名之间不能跨过域名来发送请求或者请求数据)
  5. 性能

    • 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.
      (内存型的session另说)
  6. 解耦

    • 不需要绑定到一个特定的身份验证方案。
      Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.

使用 token 时需要考虑的问题

  • 如果你认为用数据库来存储 token 会导致查询时间太长,可以选择放在内存当中。比如 redis 很适合你对 token 查询的需求。

  • token 完全由应用管理,所以它可以避开同源策略

  • token 可以避免 CSRF 攻击(因为不需要 cookie 了)

  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

refresh Token

简述

当用户登录的时候,生成access_token和refresh_token,并返回给APP。
当access_token失效时,APP使用refresh_token来请求刷新token。
如果refresh_token过期,需要用户重新登录,。也就是说,用户每一次登陆的时候refresh_token都会重新更改

Token 验证

在这里插入图片描述

refresh Token

在这里插入图片描述

对比session与token

作为身份认证,token安全行比session好;
Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 而Token ,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App 。其目的是让 某App有权利访问 某用户 的信息。

对比token与cookie

Cookie是不允许垮域访问的,但是token是支持的, 前提是传输的用户认证信息通过HTTP头传输;

token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件;cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。

JWT

什么是JWT

JWT官网
json web token(阮一峰老师对JWT的介绍),(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,以JSON对象的方式在各方之间安全地传输信息,因为是基于数字签名所以可以进行验证和信任,常用的算法比如有HMAC、RSA等等。

JWT的产生

  1. json web token(阮一峰老师对JWT的介绍)
  2. 组成:
    header、payload、签证
  3. 产生原理和流程
 4. 在头部信息中声明加密算法和常量, 然后把header使用json转化为字符串
 5. 在载荷中声明用户信息,同时还有一些其他的内容;再次使用json 把载荷部分进行转化,转化为字符串
 6. 使用在header中声明的加密算法和每个项目随机生成的secret来进行加密, 把第一部分字符串和
   第二部分的字符串进行加密, 生成新的字符串。词字符串是独一无二的。
 7. 解密的时候,只要客户端带着JWT来发起请求,服务端就直接使用secret进行解密。

在这里插入图片描述

JWT的特点汇总

  1. 三部分组成,每一部分都进行字符串的转化
  2. 解密的时候没有使用数据库,仅仅使用的是secret进行解密。
  3. JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
  4. JWT验证客户端发来的token信息, 在服务端使用密钥校验就可以((校验也是 JWT 自己实现的)),不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。

使用 JWT 时需要考虑的问题

  • 因为 JWT 并不依赖 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)

  • JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

  • JWT 不加密的情况下,不能将秘密数据写入 JWT。

  • JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

  • JWT 最大的优势是服务器不再需要存储 Session,使得服务器认证鉴权业务可以方便扩展。但这也是 JWT 最大的缺点:由于服务器不需要存储 Session 状态,因此使用过程中无法废弃某个 Token 或者更改 Token 的权限。也就是说一旦 JWT 签发了,到期之前就会始终有效,除非服务器部署额外的逻辑。(处理方式参考:签名可以加时间戳或这其他随机参与加密,一旦登录就更新签名,之前的签名失效,不会出现多个在线啦)

  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

  • JWT 适合一次性的命令认证,颁发一个有效期极短的 JWT,即使暴露了危险也很小,由于每次操作都会生成新的 JWT,因此也没必要保存 JWT,真正实现无状态。

  • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

使用加密算法时需要考虑的问题

  • 绝不要以明文存储密码

  • 永远使用 哈希算法 来处理密码,绝不要使用 Base64 或其他编码方式来存储密码,这和以明文存储密码是一样的,使用哈希,而不要使用编码。编码以及加密,都是双向的过程,而密码是保密的,应该只被它的所有者知道, 这个过程必须是单向的。哈希正是用于做这个的,从来没有解哈希这种说法, 但是编码就存在解码,加密就存在解密。

  • 绝不要使用弱哈希或已被破解的哈希算法,像 MD5 或 SHA1 ,只使用强密码哈希算法。

  • 绝不要以明文形式显示或发送密码,即使是对密码的所有者也应该这样。如果你需要 “忘记密码” 的功能,可以随机生成一个新的 一次性的(这点很重要)密码,然后把这个密码发送给用户。

对比Token和JWT

  • 相同
    • 都是访问资源的令牌
    • 都可以记录用户信息
    • 都是使服务端无状态化
    • 都是只有验证成功后,客户端才能访问服务端上受保护的资源
  • 区别
    • 服务端验证客户端发来的token信息要进行数据的查询操作;
    • JWT验证客户端发来的token信息就不用, 在服务端使用密钥校验就可以(校验也是 JWT 自己实现的),不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值