【51CTO.com快译】一个项目你搞了六个月,突然你意识到一开始做出的一个小小的简单假设完全错误。而现在你需要修复问题,同时保持现有系统正常运行;不用说,耗费的精力比当初一开始就弄好要多得多。
今天我想告诉诸位一个常见的错误,仅仅一个词会给你带来无尽的麻烦。我指的是“用户”这个词。
这个词存在两个基本问题:
1. “用户”几乎从来无法很好地描述你的需求。
2. “用户”助长了一个基本的安全设计缺陷。
“用户”这个概念含糊不清,建议你使用更准确的术语。
你没有用户
首先,没有哪个软件系统实际上有“用户”。乍一看,“用户”是很到位的描述,但一旦你更认真地分析,就会认识到你的业务逻辑实际上更复杂。
我们将考虑三个例子,先说一种极端情况。
航空公司预订系统没有“用户”
我曾为一套航空公司预订系统开发过访问控制逻辑。以下是一小部分需求:
- 如果乘客有预订号(PNR),可以通过网站查看预订。
- 如果购票者有信用卡号码的***4位数字,可以通过网站修改预订。
- 旅行代理人可以查看和修改通过其旅行社完成的预订。
- 有了乘客的身份信息,航空登记代理人可以根据其角色和机场来查看和修改预订。
不一而足。与人员对应的几个基本概念是“乘客”、“代理人”(网站也可能是代理人)和“购票者”。“用户”这个概念根本就没用,我们根本没有用这个词――比如在许多请求中,我们要加入乘客和代理人的登录信息(credential)。
Unix没有“用户”
不妨看一个全然不同的情况。Unix(如今名为POSIX)有用户:用户可以登录并运行代码。这似乎很好,是不是?但不妨仔细看一下。
如果我们果真经历了所谓的用户活动,我们有:
- 通过终端或图形用户界面登录的人员。
- 还有以“用户”的身份来运行的系统服务(比如邮件或Web服务器),比如nginx可能以httpd用户的身份来运行。
- 在服务器上,常常有多个人员共享的管理帐户,这些人使用该“用户”进行SSH连接(比如,ubuntu是运行Ubuntu的AWS虚拟机上的默认SSH帐户)。
- root,它与上述任何一个都不完全相同。
这是四个截然不同的概念,但在POSIX中它们都叫“用户”。正如我们稍后会看到的,将所有这些概念笼统称之为“用户”这个模糊概念可能会导致许多安全问题。
但就实际操作上,我们甚至没有办法在POSIX用户模式的边界内说“只有Alice和Bob可以登录到共享的管理员帐户。”
SaaS提供商没有“用户”
Jeremy Green最近在推文中提到了软件即服务(SaaS)中的用户模式,这促使我写下了这篇文章。他的基本观点是,SaaS服务几乎总是有:
- 一家企业组织中花钱购买服务的人。
- 该企业组织中一个或多个实际使用该服务的人。
如果你一开始将这些人合并成一个“用户”,就会陷入痛苦的深渊。你无法为团队建模,也无法同时针对多个人为支付建模,现在你需要改造系统。
但这只是表明一个更广泛问题的一个情况:“用户”这个概念太模糊了。如果你一开始怀疑“用户”这个词,极有可能最终意识到你实际上至少有两个概念:团队(花钱支付和拥有所有权的单位)和团队成员(实际使用服务的人) 。
“用户”是安全问题
“用户”这个词不仅仅对业务逻辑来说是个问题:它还有严重的安全后果。“用户”这个词太含糊了,将两个全然不同的概念混为一谈:
- 人员。
- 人员在软件中的表示。
想明白为什么这是个问题,假设你访问了一个恶意网站,该网站托管了一个利用浏览器缓冲区溢出的图片。远程站点现在控制你的浏览器,开始将你的所有文件上传到其服务器。为什么它能这么做?
因为你的浏览器作为你的操作系统这个“用户”来运行,该“用户”被认为与你这个人一样,其实你是一种全然不同的“用户”。你这个用户不想上传那些文件。操作系统帐户(它也是用户)可以上传那些文件,又由于你的浏览器在你的用户下运行,因此它的所有操作被认为是你想要执行的操作。
这就是所谓的困惑的代理问题(Confused Deputy Problem)。如果你使用“用户”这个词来描述两个根本不同的东西是一回事,这个问题极有可能成为你设计的一部分。
预先设计的重要性
想成为高效的程序员,关键是花更少的精力完成同样的工作。使用“用户”这样的含糊术语为软件建模需要以后花费大量的时间和精力来修复。立即开始编写代码似乎很高效,但事实恰恰相反。
下次你开始搞新的软件项目时,花几个小时预先确定术语和概念:你仍然无法做到完全正确,但结果会好得多。将来你会庆幸自己避免了种种无为的劳动。
原文标题:Never use the word “User” in your code,作者:Itamar Turner-Trauring
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】