嗯,日前 是无解了。
我们的初衷是,不让任何人可以调用我们的接口,只能通过页面看到信息。
现在我们打算不做 WEB 版,只做 APP 。
内嵌 VUE(因为要做ANDROID/IOS原生开发太...), HTTPS+动态AES调用接口,密钥KEY存在 APP 里,APP 加固,可能会把价格和剩余数量做成随机图片地址返回。
再次谢谢各路大神提供的方案。你们都超厉害的,超赞的,我好喜欢!
1
CEBBCAT 2020-08-05 10:23:21 +08:00 via Android
clientId,clientKey 哪里来的? token 不能存到 cookie 里面吗?
|
2
BruceXHe OP @CEBBCAT clientId,clientKey 是一个固定的值,token 可以存储,但是别人知道了 clientId,clientKey 就可以获取到 token
|
3
takemeaway 2020-08-05 10:28:22 +08:00
建议参考微信支付的 token 是怎么设计的。
|
4
yaphets666 2020-08-05 10:28:34 +08:00
写死在前端没事 前端代码也是会压缩 混淆的 看不出来的
|
5
dubenshu 2020-08-05 10:29:46 +08:00
可以使用 Vault 来管理 secrets
|
6
renmu123 2020-08-05 10:30:27 +08:00 via Android
你前端发一个请求到后端,值分别是 clientid 和 clientkey,然后后端把 token 值再返回就可以了。
|
7
BruceXHe OP @yaphets666 看得出来
|
8
BruceXHe OP @renmu123 对,但是别人拿到你前端 的 JS 后,可以找到 clientid 和 clientkey, 这样他就能随意获取 TOKEN 了
|
9
des 2020-08-05 10:33:04 +08:00
固定值本来就不安全,你们咋设计的啊?
|
10
chendy 2020-08-05 10:33:17 +08:00 4
clientId,clientKey 一般是服务对服务用的,前后端对接哪来的这一说?
|
11
kop1989 2020-08-05 10:34:48 +08:00
clientId 和 clientKey 是写死的?那跟无参数直接申请 token 有什么区别?探讨安全性意义又何在?
|
12
BruceXHe OP @takemeaway 支付的话,有用户 ID 之类的东西存在,ID 是动态的,和我这里情况好像不太一样,
|
13
maichael 2020-08-05 10:38:07 +08:00
写死就等于没有,这样做免登是不行的。
|
14
lower 2020-08-05 10:38:16 +08:00
后端提供一个 getToken 接口呀,
|
15
BruceXHe OP @chendy 现在这不是在讨论设计哇?要保护 API 防止被滥用(加 TOKEN ),但是获取前端 TOKEN 的话,别人肯定也可以模拟获取
|
17
zzzmh 2020-08-05 10:39:13 +08:00
@yaphets666 不说混淆最终都可以反编译出来,就楼主这个需求,他肯定要请求接口,F12 看 network 就看到传入和返回参数了。
|
20
libook 2020-08-05 10:39:57 +08:00
前端环境应始终是不受信任的,所以任何敏感信息不要放在前端。
完全不清楚你的 Token 是用来做什么的,为什么不用账号密码反而用 cleintid 和 clientkey,Token 和 clientid/clientkey 到底是什么关系,这些需求背景你得讲清楚,大家详细了解到你想做什么才能帮到你。 如果只是希望在前端存一个东西,且不希望别人知道内容,但同时希望服务端能知道内容,可以用非对称加密,加密后把密文存在前端,服务端解密后读取内容。但这个很可能不适用于你的安全场景,因为获取 Token 不需要知道密文的原文,只需要把密文发给服务端就可以拿到 Token 了。 |
23
zhoufenfens 2020-08-05 10:43:35 +08:00
请求加签名, 加上时间戳,path,salt 等关键参数,后端看来源 referer
|
24
maichael 2020-08-05 10:45:02 +08:00
@BruceXHe 可以拿 fingerprint 之类的信息,然后从后端获取公钥做非对称加密,然后限定指定的 fingerprint 才有权限,密钥对也可以做轮换。
|
25
BruceXHe OP @libook 好的,抱歉,我再说一下我的场景。
我们有一个商品列表,商品详情接口,VUE 页面展示用,但是这个接口在用户没有登陆的时候是可以看到了的。 当然购买的时候需要登陆,这个是没问题的。 因为这些商品是一些比较敏感的数据(商品是我们的优势,我们不想登陆之后才看得到,但是要也防止被人利用),我们就想着怎么保护这个接口。 背景大概是这样! 你可以理解和 clientid/clientkey/token 没有半毛钱关系 |
28
BruceXHe OP @maichael 嗯,我们的初衷是,不让任何人可以调用我们的接口,只能通过页面看到信息。现在我们打算不做 WEB 版,只做 APP (内嵌 VUE,密钥存在 APP 里,APP 加固)
|
29
KuroNekoFan 2020-08-05 10:53:05 +08:00 via iPhone
jwt 完事
|
31
None123 2020-08-05 10:53:26 +08:00
无解
|
32
wjhjd163 2020-08-05 10:55:44 +08:00 via Android
@KuroNekoFan 和 jwt 有啥关系,他不需要鉴权
|
33
wjhjd163 2020-08-05 10:56:52 +08:00 via Android
建议加入 rand,time 等参数通过一系列复杂的计算得出一个计算值,再和后端进行比对。
前端加密部分代码保护好,加上接口限速和云端风控至少破解成本会大大增加 |
34
baiyi 2020-08-05 10:59:30 +08:00
需求和现有逻辑冲突,无解。只能提高他们自动化获取的难度,不可能没办法获取
|
35
BruceXHe OP |
36
yushiro 2020-08-05 11:03:30 +08:00 via iPhone
限制接口的调用频率,前端页面缓存数据。
被人滥用无非就是高频率的调用,否则你就当 TA 是普通人呗。 |
37
dzdh 2020-08-05 11:04:28 +08:00
难道不是 类 OAuth 的用户名密码换取凭据然后凭据+ssl 吗
|
38
yeept 2020-08-05 11:05:28 +08:00
如楼上所说,按你描述的需求,只需要网关限制接口的调用频率即可
|
39
wjhjd163 2020-08-05 11:05:38 +08:00 via Android
@BruceXHe 内嵌 VUE 也可以通过抓包方法获得 Token 的获取过程,如果真准备只做 APP 那就不应该继续采用内嵌 WEB 方案,而是所有接口都做加解密,保证数据即使窃取到也不可读
|
40
wangxiaoaer 2020-08-05 11:06:27 +08:00
通过 clientId,clientKey 获得 token 本身就不应该通过前端获取。
一般涉及到 clientId,clientKey 的都是第三方应用接入才这么干,第三方应用服务器直接跟你们服务器交互,通过 id 和 key 获取 token 。 你们自己的内部的应用用这种方式怕不是闲的蛋疼,难道每一个新的浏览器就开一个新的 clientid ?必然不是啊,那问题就来了,所有用户都用同样的 id 和 key,那还有什么意义呢? |
41
baiyi 2020-08-05 11:22:13 +08:00
@BruceXHe #35 web 也可以混淆,再加上防重放等手段,但这些都是防止其他应用通过自动化手段直接获取你的数据给他们使用,防不了敏感数据的暴露,完全可以人工获取。
可以整理一下业务逻辑,是不是真的是敏感数据,还是说可接受暴露的数据 |
42
libook 2020-08-05 11:23:00 +08:00
只要不经过服务端的认证,理论上不可能达到接口保护的目的。更何况即便加上了认证,滥用者也可以注册一个账号,然后用经过验证的环境来滥用接口。
只要前端不经过认证能访问商品的接口,那么商品接口就能被自动化调用,进而被滥用。 一种折中的方法是上反爬虫(如 CAPTCHA )方案,就像你在很多网站看到的所谓“安全检测”的页面,其实是对你的整体情况进行分析来判断你是不是机器人或攻击者。 另外 WAF 也可能有些防御作用。 |
43
dingjs 2020-08-05 11:29:47 +08:00
CSRF
|
44
paulee 2020-08-05 11:29:57 +08:00
建议在问题里面追加一下背景,另外前端没法解决这个问题(反爬),可以沉了
|
45
darrenfang 2020-08-05 11:30:20 +08:00
可以用 oauth2 的 implicit 模式来获取 token,在登录页面验证 recaptcha 或者加上图形验证码。
|
46
Hyseen 2020-08-05 11:32:33 +08:00
关键字:CSRF
|
47
YoRolling 2020-08-05 11:32:52 +08:00
要不 了解一下字体反爬? 接口返回’a‘, 通过字体渲染出来的是 ’b‘。
|
48
whitehack 2020-08-05 11:36:20 +08:00
你这种需求, 不管 web 端还是 app 端 都可以用 wss 来通信. 通信内容也自己做加密, 这方面的方法就太多了.
|
49
rioshikelong121 2020-08-05 11:40:38 +08:00
使用 clientId, key 像是基于客户端的验证,这种一般肯定不会放在前端的呀。无法避免风险。
|
50
opengps 2020-08-05 11:42:20 +08:00
clientId,clientKey 是怎么个用法?我理解的 token 是登录成功分配一个授权 token,登录不成功用的 token 后端标记为匿名属性,有限访问接口
如果你想 clientId,clientKey 来保证授权,那么对方应该有个自己的简易后端来存储 clientId,clientKey,从自己的后端发起请求拿到有效 token,然后让 token 暴露到前端使用 |
51
angryfish 2020-08-05 12:07:02 +08:00 via iPhone
可以最大限度做到破解的。clientid 由 app 加密生成。算法保密。
|
52
imnpc 2020-08-05 12:18:00 +08:00
clientId,clientKey 我这里是颁发给 APP 使用 但是除了这个 还需要用户名 + 密码 才能去拿到 token 的
|
53
dustinth 2020-08-05 12:25:16 +08:00
就是反爬, 现在这种方案解决不了任何问题. 一定要有个"鉴权"发 Token 的步骤. 这个鉴权是广义的鉴权, 比如鉴定你是一个人类(常见的 Google 那种"我不是机器人"的按钮). 然而真有心爬, 人工加模拟人工都是可以爬到的, 就是个成本的问题.
|
54
KuroNekoFan 2020-08-05 12:25:23 +08:00
@wjhjd163 jwt 又不是只能用来鉴权
|
55
renmu123 2020-08-05 12:30:25 +08:00 via Android
@BruceXHe 你这个是一个反爬的需求了,我提两个点,可以将关键数据转换为图片,比如说价格,还可以使用字体替换等方法。第二种还是请求借口的时候返回一个 token,让后端验证,这个 token 的计算方法要很复杂,用 js 做各种乱七八糟的的转换,尽量提高爬虫解析 js 的难度。如果成本过高,很少会有人闲得爬你们数据。还有就是服务端做 ip 黑名单之类的东西了。。当然以上说的这些客户端反爬手段,技术好的爬虫都能解决,只能提高他们的解决成本
|
56
chinvo 2020-08-05 12:41:00 +08:00 via iPhone
接口防滥用不是这么玩的
所有前端手段都不能防止滥用 应该在后端做限制 包括 qps 、配额、异常流量识别 |
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 被破了 那就无所谓了 反正是防不住了...... 最终目的就是增加破解成本了 复杂度上去了 那么 就相对安全了 毕竟不是什么大利益的项目 不值得破下去 |
58
suzic 2020-08-05 13:00:55 +08:00 via Android
用过这种类似的方式加密接口,前端给后端发的 token 是通过 key 和后端约定好的加密过的字符串,后端拿来对比。一般没什么问题,反爬还是不够的
|
59
LifStge 2020-08-05 13:06:14 +08:00
@LifStge 其实吧 既然都限定 app 了 就不要暴露那么多接口了 直接前面说的 动态 token 的方式 剩下的改动就是 不要直接 去请求网络接口 而是所有流量都走一条 https 的 TCP 链接就行了 token 啥的 用于建立连接 协议 就走 rpc 就行了
然后服务端做做异常流量清洗 ip 拉黑啥的 就够了 比较稳了 |
61
wangyzj 2020-08-05 13:13:34 +08:00
你把你的逻辑放在后端
前端用 jwt |
62
wjhjd163 2020-08-05 13:18:06 +08:00 via Android
@KuroNekoFan 那在楼主这个环境中,jwt 应该充当什么角色呢?
|
63
zachlhb 2020-08-05 13:20:12 +08:00 via Android
如果是 web 项目的话可以考虑用 ip 白名单
|
64
manzhiyong 2020-08-05 13:31:47 +08:00
自制随机字体,页面上显示和爬虫抓回去的源码不一样,这样就可以做到反爬了
|
65
warcraft1236 2020-08-05 13:37:59 +08:00
我就说一种情况你们就防不了,UI 自动化,管你是 web 还是 app,我用自动化测试的方式抓你的数据还不是效率问题?
|
66
shynome 2020-08-05 13:40:25 +08:00 via Android
在客户端再做一次混淆编码,在 .so 文件里实现
这是常用的反破解的手段 |
67
shynome 2020-08-05 13:44:25 +08:00 via Android
同一段内容可以根据时间采用不同的加密方式,这样在不清楚加密方式的情况下想使用接口几乎是不可能的
|
68
xi_lin 2020-08-05 13:45:21 +08:00
针对原文问题,客户端一般用 PKCE 模式来规避前端保存 screct 的问题
|
69
isnullstring 2020-08-05 13:57:54 +08:00
限制同一 TOKEN 短时间内请求次数啊
至于 Token 怎么生成,上面的老哥也说了,clientId,clientKey 固定在代码,基础的防御都做不了 |
70
KuroNekoFan 2020-08-05 14:25:36 +08:00
@wjhjd163 jwt 的意义不只在于 payload 里面混淆的 data,secret 和 signature 的设计可以在一定程度上确保`这个 token 是可以被信任的`
|
71
KuroNekoFan 2020-08-05 14:28:06 +08:00
@wjhjd163 当然我又看了一下楼主的描述,考虑最糟糕的设计,clientId,clientKey 相当于 secret,那,怎么搞都不行
|
73
winglight2016 2020-08-05 14:38:57 +08:00
神奇的设计,涉及安全身份的内容为啥是写死在前端的? token 一般不都是用户输入用户名密码才能获取的吗?如果没这个登录需求,那么 koken 还有什么用?
需要反爬的话,不能按照登录验证这种思路来设计。 |
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 需要在服务端进行校验,检测内容和接口可以偶尔进行升级。 |
76
exonuclease 2020-08-05 14:53:50 +08:00
这不是为了安全是为了反爬虫?无解除非你强制用户登录才能看
|
77
Torpedo 2020-08-05 16:04:47 +08:00
|
78
wednesdayco 2020-08-05 18:03:18 +08:00
既然是 APP 内嵌 所有需要加密都请求都走 APP 协议,让 app 去反扒呗
|
79
unclemcz 2020-08-05 18:03:58 +08:00
根据时间戳加密,加密算法写入.so ,时间戳和加密后字符串一起传到后端,判断时间戳和服务器时间,比如控制延迟为 1s ;同样的加密算法计算加密字符串,和传入的加密字符串比较,这样基本可以防止爬虫。
|
80
ChanKc 2020-08-05 18:55:52 +08:00 via Android
一般这种设计的后端就是不允许 Web 直接调用的
|
81
rrfeng 2020-08-05 19:45:26 +08:00
网络抓个包随便看……对于想要看的人来说毫无难度。
|
82
DeepCold 2020-08-05 20:16:10 +08:00
拉个 node 当中间层 做服务端渲染,就能避免暴露后端接口了,应该是最佳解决办法。
|
83
sampeng 2020-08-05 21:09:29 +08:00 via iPhone
问题应该是反扒,而不是只有你的 js 才能访问到。
说的最简单点,我要爬你的东西,先本地装个根证书,看你请求详情,然后直接拿这个去跑脚本…防小白就是直接 js 里面做点反扒的手段。 另外说一嘴,网络安全在于你数据对别人有没价值,而不是对你有没价值。商品详情而已,防爬攻防战咯。还一种蠢办法。生成的是图片不是文字。服务端吐出图片和文字混排的…我上次想爬时光网就发现他是这么干的…无语的不行。 了解一下 webassembly,直接二进制。破解难度应该远大于混淆过的 js 。绝大多数浏览器新版支持。 |
84
icecreamxuegao 2020-08-06 09:26:51 +08:00
哪怕 js 压缩混淆了,直接抓包不也能抓出来吗
|
85
a728976009 2020-08-06 09:37:14 +08:00
oauth2 有 implict 模式和 pkce 模式可以让前端在不知道 secret 的情况下拿 token,但看起来你的后端不是 oauth,所以建议改设计
|
86
cyrbuzz 2020-08-06 10:01:49 +08:00
用 Nuxt 在服务器端执行获取逻辑?
|
87
jake361 2020-08-12 10:08:41 +08:00
不让别人调用你们的接口?
有跨域问题你怕啥,你可以让后端只允许某个域名调用不就 ok 了 |