假设我们的系统登录需要用客户信息授权, 我们需要知道某个 email 是否是客户的员工。
客户提供一个员工表的账号,通过这个账号,我们可以读到如下数据表
... | phone | password | ... | |
---|---|---|---|---|
pony@tct.inc | 1882375662 | 4b3e3c2f99046f9 | ||
ntmgr@tct.inc | 1726639880 | d0cd2693b35066 | ||
pk1_sgmgr@tct.inc | 1783305223 | e55f86a1f9e06e5 |
客户将这个账号设为只读账号,防止我们不小心修改员工表信息。
通过上表,我们可以将用户 email 和上表 email 进行比对,实现验证。
用户使用我们的系统时,在我们的登录页输入框中输入自己的 email,我们拿到用户 email 后将用户提供的 email 和客户数据库中的 email 对比,验证成功后进入系统。
系统平稳运行三个月。
客户表示,这种方式我们可以遍历员工表,可以获知他们公司的员工组成。
于是我们联系客户,改成了第二种方式。
客户提供一个方法
(email) => boolean
复制代码
这个方法暴露为接口,我们调用这个接口验证用户的 email 是否正确。这种方法我们无法读取到客户公司所有的 email。
但我们可以用编造出来的很多 email 请求这个接口,通过返回的是否是本公司员工猜出客户公司的员工组成。考虑到这一点,客户设计接口时增加了接口调用限制,一天 200 次请求,这样可以防止我们用接口去试客户公司的员工 email,进而得到它们的员工组成信息。
系统平稳运行三个月。
我们发现,即使我们不通过编造大量 email 地址请求验证接口,快速猜出客户公司员工组成。每次用户使用我们的系统,需要输入有效的客户公司 email 验证。如果我们记录用户的 email,一段时间下来,还是能得到客户公司的员工组成信息。
也就是说,用户账号不能流经我们的系统。
于是我们提出,我们的前端页面拿到用户账号后,先进行 MD5 加密,加密后传入我们的系统,我们将 MD5 传给客户,客户进行比对,返回给我们是否账号属于客户的组织。
这样我们即使存储,存储的也是一堆 MD5,我们并不能反推出用户的组织都有哪些 email。
系统平稳运行三个月。
客户表示,即使我们对他们保证我们在前端页面拿到用户输入的账号后,立即转换成 MD5 传入我们的系统,也不能保证我们未来一定不会收集账号。
为了满足客户的需求,我们需要,用户的账号不能出现在我们系统的任何一个部分,也包括前端的输入框。
也就是说对客户而言,用户不能在我们的输入框中输入自己的账号。
同时对我们而言,我们需要一个信息,来标识用户的账号,而这个信息我们无法解密出有效信息。
用户不能在我们的输入框中输入账号,那一定只能在客户的页面中输入自己的账号。
我们需要一个信息,这个信息标识了用户的信息,但我们无法解密。
而我们这里也有一个输入框,原来输入的是用户账号,现在输入的是加密的信息。
那么流程就可以是
- 用户访问客户网站,输入账号
- 客户网站返回一串 MD5
- 用户将 MD5 复制粘贴到我们网站的原账号输入框
- 用户点击登录,我们将 MD5 传给客户认证接口,验证成功进入我们的系统
这里有个问题,就是用户此时需要用的是我们的网站,却需要打开客户的地址,因此可以增加一步:
- 用户访问我们的网站,我们的网站跳转到客户网站
- 用户在客户网站,输入账号
- 客户网站返回一串 MD5
- 用户将 MD5 复制粘贴到我们网站的原账号输入框
- 用户点击登录,我们将 MD5 传给客户认证接口,验证成功进入我们的系统
这里有一处可以自动化的地方:客户网站时可以返回 MD5 给我们的网站的,因此可以改为:
- 用户访问我们的网站,我们的网站跳转到客户网站
- 用户在客户网站输入框输入账号,客户网站认证成功后跳转我们的网站,带上 MD5
- 我们的网站将 MD5 传给客户网站进行认证,验证成功后进入我们的系统
这个方案对我们来讲,我们自始至终我们传递的是一个我们无法解密的字符串,解决了烫手的用户信息问题。
对于客户来讲,email 只在自己的系统中流转,不会泄露出去,email 本身带有的一些信息不会被外部获知到。对于用户来讲,原来的登录步骤是在我们的系统输入 email, 点击登录后进入我们的系统,现在登录我们的系统时,我们的系统会跳转到另一个页面,在那个页面输入账号后点击授权,会跳回到我们的网页,然后进入我们的系统。
实际的 OAuth 为了适应一些不安全的网络环境,增加了一些额外的字段或步骤,同时核心原理也是这样的。
近期评论