V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
BruceXHe
V2EX  ›  Vue.js

关于前端 token 安全问题

  •  
  •   BruceXHe · 2020-08-05 10:18:59 +08:00 · 9690 次点击
    这是一个创建于 1600 天前的主题,其中的信息可能已经有所发展或是发生改变。
    前端:VUE

    后台:.NET CORE REST API

    现在我们后台的接口,需要 TOKEN,TOKEN 通过 clientId,clientKey 获取的(非用户输入用户名和密码),
    目前只有把 clientId,clientKey 配置在 VUE 代码里用于获取 TOKEN,但是这样就不安全了。

    请问大家有什么办法?
    第 1 条附言  ·  2020-08-05 14:39:32 +08:00

    嗯,日前 是无解了。

    我们的初衷是,不让任何人可以调用我们的接口,只能通过页面看到信息。

    现在我们打算不做 WEB 版,只做 APP 。

    内嵌 VUE(因为要做ANDROID/IOS原生开发太...), HTTPS+动态AES调用接口,密钥KEY存在 APP 里,APP 加固,可能会把价格和剩余数量做成随机图片地址返回。

    再次谢谢各路大神提供的方案。你们都超厉害的,超赞的,我好喜欢!

    88 条回复    2020-08-12 10:11:07 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2020-08-05 10:23:21 +08:00 via Android
    clientId,clientKey 哪里来的? token 不能存到 cookie 里面吗?
    BruceXHe
        2
    BruceXHe  
    OP
       2020-08-05 10:26:23 +08:00
    @CEBBCAT clientId,clientKey 是一个固定的值,token 可以存储,但是别人知道了 clientId,clientKey 就可以获取到 token
    takemeaway
        3
    takemeaway  
       2020-08-05 10:28:22 +08:00
    建议参考微信支付的 token 是怎么设计的。
    yaphets666
        4
    yaphets666  
       2020-08-05 10:28:34 +08:00
    写死在前端没事 前端代码也是会压缩 混淆的 看不出来的
    dubenshu
        5
    dubenshu  
       2020-08-05 10:29:46 +08:00
    可以使用 Vault 来管理 secrets
    renmu123
        6
    renmu123  
       2020-08-05 10:30:27 +08:00 via Android
    你前端发一个请求到后端,值分别是 clientid 和 clientkey,然后后端把 token 值再返回就可以了。
    BruceXHe
        7
    BruceXHe  
    OP
       2020-08-05 10:30:56 +08:00
    @yaphets666 看得出来
    BruceXHe
        8
    BruceXHe  
    OP
       2020-08-05 10:31:47 +08:00
    @renmu123 对,但是别人拿到你前端 的 JS 后,可以找到 clientid 和 clientkey, 这样他就能随意获取 TOKEN 了
    des
        9
    des  
       2020-08-05 10:33:04 +08:00
    固定值本来就不安全,你们咋设计的啊?
    chendy
        10
    chendy  
       2020-08-05 10:33:17 +08:00   ❤️ 4
    clientId,clientKey 一般是服务对服务用的,前后端对接哪来的这一说?
    kop1989
        11
    kop1989  
       2020-08-05 10:34:48 +08:00
    clientId 和 clientKey 是写死的?那跟无参数直接申请 token 有什么区别?探讨安全性意义又何在?
    BruceXHe
        12
    BruceXHe  
    OP
       2020-08-05 10:35:20 +08:00
    @takemeaway 支付的话,有用户 ID 之类的东西存在,ID 是动态的,和我这里情况好像不太一样,
    maichael
        13
    maichael  
       2020-08-05 10:38:07 +08:00
    写死就等于没有,这样做免登是不行的。
    lower
        14
    lower  
       2020-08-05 10:38:16 +08:00
    后端提供一个 getToken 接口呀,
    BruceXHe
        15
    BruceXHe  
    OP
       2020-08-05 10:38:28 +08:00
    @chendy 现在这不是在讨论设计哇?要保护 API 防止被滥用(加 TOKEN ),但是获取前端 TOKEN 的话,别人肯定也可以模拟获取
    BruceXHe
        16
    BruceXHe  
    OP
       2020-08-05 10:38:58 +08:00
    @maichael 有什么好的办法没有?
    zzzmh
        17
    zzzmh  
       2020-08-05 10:39:13 +08:00
    @yaphets666 不说混淆最终都可以反编译出来,就楼主这个需求,他肯定要请求接口,F12 看 network 就看到传入和返回参数了。
    BruceXHe
        18
    BruceXHe  
    OP
       2020-08-05 10:39:24 +08:00
    @lower 想过,不行的。这个 getToken 的办法,别人一样或者调用
    zzzmh
        19
    zzzmh  
       2020-08-05 10:39:56 +08:00
    @BruceXHe 前后端都 AES 加密,AES 密钥放前端,这招可以治标不治本,治本没办法,根本上换一套设计
    libook
        20
    libook  
       2020-08-05 10:39:57 +08:00
    前端环境应始终是不受信任的,所以任何敏感信息不要放在前端。

    完全不清楚你的 Token 是用来做什么的,为什么不用账号密码反而用 cleintid 和 clientkey,Token 和 clientid/clientkey 到底是什么关系,这些需求背景你得讲清楚,大家详细了解到你想做什么才能帮到你。

    如果只是希望在前端存一个东西,且不希望别人知道内容,但同时希望服务端能知道内容,可以用非对称加密,加密后把密文存在前端,服务端解密后读取内容。但这个很可能不适用于你的安全场景,因为获取 Token 不需要知道密文的原文,只需要把密文发给服务端就可以拿到 Token 了。
    BruceXHe
        21
    BruceXHe  
    OP
       2020-08-05 10:40:11 +08:00
    @zzzmh HTTPS 的话,F12 是看不到的,但是你请求的参数写死的话,在 JS 代码里肯定找得到
    renmu123
        22
    renmu123  
       2020-08-05 10:42:19 +08:00
    @BruceXHe #8 你们是内部后台管理系统还是面向 c 端或者 b 端的什么系统,这个要看场景
    zhoufenfens
        23
    zhoufenfens  
       2020-08-05 10:43:35 +08:00
    请求加签名, 加上时间戳,path,salt 等关键参数,后端看来源 referer
    maichael
        24
    maichael  
       2020-08-05 10:45:02 +08:00
    @BruceXHe 可以拿 fingerprint 之类的信息,然后从后端获取公钥做非对称加密,然后限定指定的 fingerprint 才有权限,密钥对也可以做轮换。
    BruceXHe
        25
    BruceXHe  
    OP
       2020-08-05 10:46:05 +08:00
    @libook 好的,抱歉,我再说一下我的场景。

    我们有一个商品列表,商品详情接口,VUE 页面展示用,但是这个接口在用户没有登陆的时候是可以看到了的。
    当然购买的时候需要登陆,这个是没问题的。

    因为这些商品是一些比较敏感的数据(商品是我们的优势,我们不想登陆之后才看得到,但是要也防止被人利用),我们就想着怎么保护这个接口。

    背景大概是这样!
    你可以理解和 clientid/clientkey/token 没有半毛钱关系
    maichael
        26
    maichael  
       2020-08-05 10:47:17 +08:00
    @BruceXHe 当然,不获取公钥,只获取一个随机因子也可以
    maichael
        27
    maichael  
       2020-08-05 10:48:39 +08:00
    @BruceXHe 那你这个场景是防止 API 被滥用,不是鉴权,你开始方向就错了。
    BruceXHe
        28
    BruceXHe  
    OP
       2020-08-05 10:52:44 +08:00
    @maichael 嗯,我们的初衷是,不让任何人可以调用我们的接口,只能通过页面看到信息。现在我们打算不做 WEB 版,只做 APP (内嵌 VUE,密钥存在 APP 里,APP 加固)
    KuroNekoFan
        29
    KuroNekoFan  
       2020-08-05 10:53:05 +08:00 via iPhone
    jwt 完事
    kop1989
        30
    kop1989  
       2020-08-05 10:53:07 +08:00
    @BruceXHe #25 又要让大家都看见,又要防止被坏人看见。这不是无解么?最多只能在反爬上下功夫了。
    None123
        31
    None123  
       2020-08-05 10:53:26 +08:00
    无解
    wjhjd163
        32
    wjhjd163  
       2020-08-05 10:55:44 +08:00 via Android
    @KuroNekoFan 和 jwt 有啥关系,他不需要鉴权
    wjhjd163
        33
    wjhjd163  
       2020-08-05 10:56:52 +08:00 via Android
    建议加入 rand,time 等参数通过一系列复杂的计算得出一个计算值,再和后端进行比对。
    前端加密部分代码保护好,加上接口限速和云端风控至少破解成本会大大增加
    baiyi
        34
    baiyi  
       2020-08-05 10:59:30 +08:00
    需求和现有逻辑冲突,无解。只能提高他们自动化获取的难度,不可能没办法获取
    BruceXHe
        35
    BruceXHe  
    OP
       2020-08-05 11:01:34 +08:00
    @baiyi 嗯,日前 是无解了。

    我们的初衷是,不让任何人可以调用我们的接口,只能通过页面看到信息。现在我们打算不做 WEB 版,只做 APP (内嵌 VUE,密钥存在 APP 里,APP 加固)
    yushiro
        36
    yushiro  
       2020-08-05 11:03:30 +08:00 via iPhone
    限制接口的调用频率,前端页面缓存数据。
    被人滥用无非就是高频率的调用,否则你就当 TA 是普通人呗。
    dzdh
        37
    dzdh  
       2020-08-05 11:04:28 +08:00
    难道不是 类 OAuth 的用户名密码换取凭据然后凭据+ssl 吗
    yeept
        38
    yeept  
       2020-08-05 11:05:28 +08:00
    如楼上所说,按你描述的需求,只需要网关限制接口的调用频率即可
    wjhjd163
        39
    wjhjd163  
       2020-08-05 11:05:38 +08:00 via Android
    @BruceXHe 内嵌 VUE 也可以通过抓包方法获得 Token 的获取过程,如果真准备只做 APP 那就不应该继续采用内嵌 WEB 方案,而是所有接口都做加解密,保证数据即使窃取到也不可读
    wangxiaoaer
        40
    wangxiaoaer  
       2020-08-05 11:06:27 +08:00
    通过 clientId,clientKey 获得 token 本身就不应该通过前端获取。

    一般涉及到 clientId,clientKey 的都是第三方应用接入才这么干,第三方应用服务器直接跟你们服务器交互,通过 id 和 key 获取 token 。

    你们自己的内部的应用用这种方式怕不是闲的蛋疼,难道每一个新的浏览器就开一个新的 clientid ?必然不是啊,那问题就来了,所有用户都用同样的 id 和 key,那还有什么意义呢?
    baiyi
        41
    baiyi  
       2020-08-05 11:22:13 +08:00
    @BruceXHe #35 web 也可以混淆,再加上防重放等手段,但这些都是防止其他应用通过自动化手段直接获取你的数据给他们使用,防不了敏感数据的暴露,完全可以人工获取。
    可以整理一下业务逻辑,是不是真的是敏感数据,还是说可接受暴露的数据
    libook
        42
    libook  
       2020-08-05 11:23:00 +08:00
    只要不经过服务端的认证,理论上不可能达到接口保护的目的。更何况即便加上了认证,滥用者也可以注册一个账号,然后用经过验证的环境来滥用接口。

    只要前端不经过认证能访问商品的接口,那么商品接口就能被自动化调用,进而被滥用。

    一种折中的方法是上反爬虫(如 CAPTCHA )方案,就像你在很多网站看到的所谓“安全检测”的页面,其实是对你的整体情况进行分析来判断你是不是机器人或攻击者。
    另外 WAF 也可能有些防御作用。
    dingjs
        43
    dingjs  
       2020-08-05 11:29:47 +08:00
    CSRF
    paulee
        44
    paulee  
       2020-08-05 11:29:57 +08:00
    建议在问题里面追加一下背景,另外前端没法解决这个问题(反爬),可以沉了
    darrenfang
        45
    darrenfang  
       2020-08-05 11:30:20 +08:00
    可以用 oauth2 的 implicit 模式来获取 token,在登录页面验证 recaptcha 或者加上图形验证码。
    Hyseen
        46
    Hyseen  
       2020-08-05 11:32:33 +08:00
    关键字:CSRF
    YoRolling
        47
    YoRolling  
       2020-08-05 11:32:52 +08:00
    要不 了解一下字体反爬? 接口返回’a‘, 通过字体渲染出来的是 ’b‘。
    whitehack
        48
    whitehack  
       2020-08-05 11:36:20 +08:00
    你这种需求, 不管 web 端还是 app 端 都可以用 wss 来通信. 通信内容也自己做加密, 这方面的方法就太多了.
    rioshikelong121
        49
    rioshikelong121  
       2020-08-05 11:40:38 +08:00
    使用 clientId, key 像是基于客户端的验证,这种一般肯定不会放在前端的呀。无法避免风险。
    opengps
        50
    opengps  
       2020-08-05 11:42:20 +08:00
    clientId,clientKey 是怎么个用法?我理解的 token 是登录成功分配一个授权 token,登录不成功用的 token 后端标记为匿名属性,有限访问接口
    如果你想 clientId,clientKey 来保证授权,那么对方应该有个自己的简易后端来存储 clientId,clientKey,从自己的后端发起请求拿到有效 token,然后让 token 暴露到前端使用
    angryfish
        51
    angryfish  
       2020-08-05 12:07:02 +08:00 via iPhone
    可以最大限度做到破解的。clientid 由 app 加密生成。算法保密。
    imnpc
        52
    imnpc  
       2020-08-05 12:18:00 +08:00
    clientId,clientKey 我这里是颁发给 APP 使用 但是除了这个 还需要用户名 + 密码 才能去拿到 token 的
    dustinth
        53
    dustinth  
       2020-08-05 12:25:16 +08:00
    就是反爬, 现在这种方案解决不了任何问题. 一定要有个"鉴权"发 Token 的步骤. 这个鉴权是广义的鉴权, 比如鉴定你是一个人类(常见的 Google 那种"我不是机器人"的按钮). 然而真有心爬, 人工加模拟人工都是可以爬到的, 就是个成本的问题.
    KuroNekoFan
        54
    KuroNekoFan  
       2020-08-05 12:25:23 +08:00
    @wjhjd163 jwt 又不是只能用来鉴权
    renmu123
        55
    renmu123  
       2020-08-05 12:30:25 +08:00 via Android
    @BruceXHe 你这个是一个反爬的需求了,我提两个点,可以将关键数据转换为图片,比如说价格,还可以使用字体替换等方法。第二种还是请求借口的时候返回一个 token,让后端验证,这个 token 的计算方法要很复杂,用 js 做各种乱七八糟的的转换,尽量提高爬虫解析 js 的难度。如果成本过高,很少会有人闲得爬你们数据。还有就是服务端做 ip 黑名单之类的东西了。。当然以上说的这些客户端反爬手段,技术好的爬虫都能解决,只能提高他们的解决成本
    chinvo
        56
    chinvo  
       2020-08-05 12:41:00 +08:00 via iPhone
    接口防滥用不是这么玩的

    所有前端手段都不能防止滥用

    应该在后端做限制

    包括 qps 、配额、异常流量识别
    LifStge
        57
    LifStge  
       2020-08-05 12:53:25 +08:00
    @BruceXHe 完全防护做不到 既然你提到了 app 加固 无非就是增加下破解的复杂度 首先再 app 不被爆破的前提下 动态获取 token 是可以的 但是固定 id 跟 key 存在客户端 然后获取 token 其实吧 这种截包 很容易发现的 这块无非就是增加下算法的复杂度 增加获取 token 的复杂度 (增肌截包分析难度, 必须走破解客户端的路子)
    比如举个例子 token 的获取流程 客户端发起 -> 然后服务器与客户端协商验证算法(这块可以做多组动态的验证) -> 然后客户端再通过协商后的算法发起 token 请求(接口都可以用是加密动态的)-> 剩下的用 token 走流程就是了
    然后再比如 为了避免截获 token 然后再保存发起请求 就可以在 token 的动态配置上做做文章 比如不同的分组啥的 不同的 token 等等了 无非就是增加下流程的复杂度 增加截包分析难度
    再比如某些接口的请求 服务端对异常请求 校验下 埋点雷 然后做拉黑啥的 (增加下破解调试复杂度)
    如果加固的 app 被破了 那就无所谓了 反正是防不住了......
    最终目的就是增加破解成本了 复杂度上去了 那么 就相对安全了 毕竟不是什么大利益的项目 不值得破下去
    suzic
        58
    suzic  
       2020-08-05 13:00:55 +08:00 via Android
    用过这种类似的方式加密接口,前端给后端发的 token 是通过 key 和后端约定好的加密过的字符串,后端拿来对比。一般没什么问题,反爬还是不够的
    LifStge
        59
    LifStge  
       2020-08-05 13:06:14 +08:00
    @LifStge 其实吧 既然都限定 app 了 就不要暴露那么多接口了 直接前面说的 动态 token 的方式 剩下的改动就是 不要直接 去请求网络接口 而是所有流量都走一条 https 的 TCP 链接就行了 token 啥的 用于建立连接 协议 就走 rpc 就行了
    然后服务端做做异常流量清洗 ip 拉黑啥的 就够了 比较稳了
    LifStge
        60
    LifStge  
       2020-08-05 13:09:00 +08:00
    @LifStge 好吧 想多了 增加复杂度了 不需要 rpc 单走 https 就行了
    wangyzj
        61
    wangyzj  
       2020-08-05 13:13:34 +08:00
    你把你的逻辑放在后端
    前端用 jwt
    wjhjd163
        62
    wjhjd163  
       2020-08-05 13:18:06 +08:00 via Android
    @KuroNekoFan 那在楼主这个环境中,jwt 应该充当什么角色呢?
    zachlhb
        63
    zachlhb  
       2020-08-05 13:20:12 +08:00 via Android
    如果是 web 项目的话可以考虑用 ip 白名单
    manzhiyong
        64
    manzhiyong  
       2020-08-05 13:31:47 +08:00
    自制随机字体,页面上显示和爬虫抓回去的源码不一样,这样就可以做到反爬了
    warcraft1236
        65
    warcraft1236  
       2020-08-05 13:37:59 +08:00
    我就说一种情况你们就防不了,UI 自动化,管你是 web 还是 app,我用自动化测试的方式抓你的数据还不是效率问题?
    shynome
        66
    shynome  
       2020-08-05 13:40:25 +08:00 via Android
    在客户端再做一次混淆编码,在 .so 文件里实现
    这是常用的反破解的手段
    shynome
        67
    shynome  
       2020-08-05 13:44:25 +08:00 via Android
    同一段内容可以根据时间采用不同的加密方式,这样在不清楚加密方式的情况下想使用接口几乎是不可能的
    xi_lin
        68
    xi_lin  
       2020-08-05 13:45:21 +08:00
    针对原文问题,客户端一般用 PKCE 模式来规避前端保存 screct 的问题
    isnullstring
        69
    isnullstring  
       2020-08-05 13:57:54 +08:00
    限制同一 TOKEN 短时间内请求次数啊
    至于 Token 怎么生成,上面的老哥也说了,clientId,clientKey 固定在代码,基础的防御都做不了
    KuroNekoFan
        70
    KuroNekoFan  
       2020-08-05 14:25:36 +08:00
    @wjhjd163 jwt 的意义不只在于 payload 里面混淆的 data,secret 和 signature 的设计可以在一定程度上确保`这个 token 是可以被信任的`
    KuroNekoFan
        71
    KuroNekoFan  
       2020-08-05 14:28:06 +08:00
    @wjhjd163 当然我又看了一下楼主的描述,考虑最糟糕的设计,clientId,clientKey 相当于 secret,那,怎么搞都不行
    BruceXHe
        72
    BruceXHe  
    OP
       2020-08-05 14:32:01 +08:00
    @ALL
    谢谢各位大佬,涨见识了!!
    winglight2016
        73
    winglight2016  
       2020-08-05 14:38:57 +08:00
    神奇的设计,涉及安全身份的内容为啥是写死在前端的? token 一般不都是用户输入用户名密码才能获取的吗?如果没这个登录需求,那么 koken 还有什么用?

    需要反爬的话,不能按照登录验证这种思路来设计。
    vone
        74
    vone  
       2020-08-05 14:39:23 +08:00   ❤️ 1
    同 .NET Core,现在做 .NET 的同行好像越来越少了。

    我可以从做爬虫的角度,给你几个改进方向:
    1 、取消 clientId , clientKey 获取 token 的逻辑,因为没有 clientId 、clientKey 会让分析接口的人更怀疑人生;
    2 、对获取 token 相关接口改为参数改为密文( RSA+其他的魔改操作),加密函数一定要混淆,且不能完全使用某种公开算法;
    3 、对请求参数增加时间戳和签名;
    4 、下发 token 时检测浏览器常见全局变量和之前预留的监测点数据(尽量防止 selenium/puppeteer 这种无头浏览器和程序的模拟请求),这一点可以参考淘宝或者其他大厂的反爬策略。
    5 、未登录下发的 token 使用增加频率限制,高频使用时墙掉对应 IP 。
    6 、随机抽取访问频率偏高但未达到 5 的 token 让其登录或输入验证码。如果对应 IP 未登录或输入验证码,而是转而获取新 Token,就可以墙掉对应 IP 。

    4 、5 、6 需要在服务端进行校验,检测内容和接口可以偶尔进行升级。
    BruceXHe
        75
    BruceXHe  
    OP
       2020-08-05 14:42:43 +08:00
    @vone 嗯嗯,谢谢,后端服务端的骚操作那是必须的。
    exonuclease
        76
    exonuclease  
       2020-08-05 14:53:50 +08:00
    这不是为了安全是为了反爬虫?无解除非你强制用户登录才能看
    Torpedo
        77
    Torpedo  
       2020-08-05 16:04:47 +08:00
    @BruceXHe 比较场景的就是通过客户端发请求。客户端用一个 token 和参数的排列,算出 md5 给服务端。

    核心是客户端混淆这个哈希算法(算法随意,md5 都行)和 token 。
    wednesdayco
        78
    wednesdayco  
       2020-08-05 18:03:18 +08:00
    既然是 APP 内嵌 所有需要加密都请求都走 APP 协议,让 app 去反扒呗
    unclemcz
        79
    unclemcz  
       2020-08-05 18:03:58 +08:00
    根据时间戳加密,加密算法写入.so ,时间戳和加密后字符串一起传到后端,判断时间戳和服务器时间,比如控制延迟为 1s ;同样的加密算法计算加密字符串,和传入的加密字符串比较,这样基本可以防止爬虫。
    ChanKc
        80
    ChanKc  
       2020-08-05 18:55:52 +08:00 via Android
    一般这种设计的后端就是不允许 Web 直接调用的
    rrfeng
        81
    rrfeng  
       2020-08-05 19:45:26 +08:00
    网络抓个包随便看……对于想要看的人来说毫无难度。
    DeepCold
        82
    DeepCold  
       2020-08-05 20:16:10 +08:00
    拉个 node 当中间层 做服务端渲染,就能避免暴露后端接口了,应该是最佳解决办法。
    sampeng
        83
    sampeng  
       2020-08-05 21:09:29 +08:00 via iPhone
    问题应该是反扒,而不是只有你的 js 才能访问到。
    说的最简单点,我要爬你的东西,先本地装个根证书,看你请求详情,然后直接拿这个去跑脚本…防小白就是直接 js 里面做点反扒的手段。

    另外说一嘴,网络安全在于你数据对别人有没价值,而不是对你有没价值。商品详情而已,防爬攻防战咯。还一种蠢办法。生成的是图片不是文字。服务端吐出图片和文字混排的…我上次想爬时光网就发现他是这么干的…无语的不行。

    了解一下 webassembly,直接二进制。破解难度应该远大于混淆过的 js 。绝大多数浏览器新版支持。
    icecreamxuegao
        84
    icecreamxuegao  
       2020-08-06 09:26:51 +08:00
    哪怕 js 压缩混淆了,直接抓包不也能抓出来吗
    a728976009
        85
    a728976009  
       2020-08-06 09:37:14 +08:00
    oauth2 有 implict 模式和 pkce 模式可以让前端在不知道 secret 的情况下拿 token,但看起来你的后端不是 oauth,所以建议改设计
    cyrbuzz
        86
    cyrbuzz  
       2020-08-06 10:01:49 +08:00
    用 Nuxt 在服务器端执行获取逻辑?
    jake361
        87
    jake361  
       2020-08-12 10:08:41 +08:00
    不让别人调用你们的接口?
    有跨域问题你怕啥,你可以让后端只允许某个域名调用不就 ok 了
    jake361
        88
    jake361  
       2020-08-12 10:11:07 +08:00
    @kop1989 这个是正解... 只能是反爬上下功夫。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   878 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 19:56 · PVG 03:56 · LAX 11:56 · JFK 14:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.