不要在代码中使用[User]这个单词!

简介: 不要在代码中使用[User]这个单词!

image.png

当你意识到你在项目开始时做的轻量、简单的设想竟然完全错了时,你已经用了六个月的时间投入到这个项目上。


现在你需要解决这些问题,才能让这个系统继续运行下去,你发现你用在这个项目上的精力远远超出了你的预期,如果一开始就用正确的方式来做,就不会发生这样的事。


今天,我要告诉你的是一个经常犯的错误,一个会给你带来无穷无尽的问题的单词,那就是“users”这个单词有两个最基本的错误:

  1. 对你的需求来说 “User” 几乎从来都不是一个好的描述。
  2. “User” 会导致一个基本的设计安全缺陷。“user” 的概念是模糊不清的,使用更精准的术语几乎总是能起到更好的效果。


你没有使用者


最开始,没有任何一个软件系统真的有使用者存在。乍一看“user”是一个好的描述,但是你稍微一想就会意识到你的业务逻辑实际上比这要复杂的多。


我会使用三个例子,从一个极端的情况出发。机票预订系统没有“users”,我曾经看过机票预订系统访问控制逻辑,下面只是一小部分需求:

  • 旅客可以使用预定记录码通过网站查看预定信息。
  • 购买者可以通过信用卡号后四位数在网站上修改预订信息。
  • 旅行社可以查看和修改他们的预订。
  • 航空公司的值机人员可以根据角色和航空公司来查看和修改预订信息,这需要旅客提供身份信息。


不再一一列举。一些与人类相关的基本概念是“旅客”,“代理”(网站也可是看作代理)和“购买者”。“user”这个概念根本没用,并且在许多请求中我根本不会使用这个单词,举个例子,我们的请求必须包括旅客和代理人的证件,而不是使用者的证件。


Unix没有“Users”


我们看一个不太一样的例子。Unix (这些天被称为POSIX)有用户,他们可以登录并执行代码。这样看起来很不错吧?我们深入看一下。


如果我们把所有都当作“users”的话,我们将会有:

  1. 使用终端或者图形界面登录的人
  2. 像邮件或者web服务器这种系统服务也会以“users”的身份运行,例如nginx可以以httpd用户运行。
  3. 在服务器上经常会有多人共享一个管理员账号用来SSH登录(例如,亚马逊的Ubuntu虚拟机默认SSH账号就是‘ubuntu’)
  4. root 身份,和上面其他身份都不同。


上面四个是几乎不同的概念,但是在POSIX上他们都是 “users”. 一会儿我们就会看到,把这些概念都称为‘user’会导致很多安全问题。


在操作上,因为POSIX的用户模型边界存在,我们甚至不能找到一种方式说“只能让 Alice 和 Bob 通过这个账号登录”。


Saas服务提供商没有“Users”


Jeremy Green 最近就用户模型在SaaS中的应用在推特上发文,它第一次提醒了我写下这篇文章,他的基本观点是


Saas服务几乎总是:

  • 某个组织中的一个人支付服务费用。
  • 一个或多个人共同使用这个服务。


如果你一开始就把这些人作为一个用户,你将会陷入一个痛苦的世界。你无法建立团队模型,你无法组建同时为多人支付的模型,然后你就会开始改造你的系统。现在你在SaaS案例中学到了一课,我们来看一看你的生活。


但是这只是众多例子中的一个:“users”的概念太模糊了。如果你开始怀疑“user”这个词,最终你可能发现最终你其实只需要两个概念:团队(用来组织关系和支付)和成员(实际使用服务的人)。


“Users”是一个安全问题


“user” 这个单词不仅是业务逻辑的问题,它也导致了一系列安全问题。

“user” 这个单词如此的模糊以至于从根本上将两个概念合并了:

  • 一个人。
  • 他们在软件中的代表性。


为了说明这个问题,假设你正在访问一个居心不良的网站,在它服务器上的图片导致了你的浏览器内存溢出。远程网站控制着你的浏览器,并且开始将你的文件上传到他的服务上。


为什么它能这样做?


因为浏览器是以系统用户的身份运行的,它被认为与人类身份的你相同,实际上你们是不同的。你作为’user’,不想上传文件。但是系统的账号也是‘user’,能够上传文件,如果浏览器运行在你的账号之下,他所有的行为会被当作是你的意图,也就是说是你让它这么做的,实际上不是。


这就是被称为Confused Deputy的问题。如果你使用“用户”这个词来描述两个根本不同的东西,那么这个问题就更有可能成为你设计的一部分。


前期设计的价值


花更少的功夫处理相同的问题是成为高产程序员的关键。使用模糊不清的概念比如“用户”来组织你的软件,将会话费大量时间和精力来解决未来发生的问题。一上来就开始编码看起来是高产的,事实恰好相反。


下次你开始一个新的软件项目时,花几个小时预先确定你的术语和概念:你仍然不会完全正确,但你会做得更好。未来的你将感谢你所做的所有预防浪费的工作。

目录
相关文章
|
3月前
|
Unix Linux
文本匹配.grep与Select-String用法对比
文本匹配.grep与Select-String用法对比
64 6
|
4月前
|
语音技术
语音识别,print(“Hello“,end=‘‘)不换行的写法,\t代表着tab,print(“H\tW“),for循环的基础语法,把字符串遍历的写法,数itheima is有几个a
语音识别,print(“Hello“,end=‘‘)不换行的写法,\t代表着tab,print(“H\tW“),for循环的基础语法,把字符串遍历的写法,数itheima is有几个a
|
6月前
|
Oracle Java 关系型数据库
Java【代码分享 06】Lamda表达式将List对象中的Map对象的key全部转化为大写或者小写(去除外层循环:可用于Map对象中的key全部转化为大写或者小写)
Java【代码分享 06】Lamda表达式将List对象中的Map对象的key全部转化为大写或者小写(去除外层循环:可用于Map对象中的key全部转化为大写或者小写)
310 0
|
Oracle 关系型数据库
oracle按code编码长度查询代码展现层级关系(给字段前加空格)
学习oracle按code编码长度查询代码展现层级关系(给字段前加空格)
152 0
oracle按code编码长度查询代码展现层级关系(给字段前加空格)
string 去掉左边空格
string 去掉左边空格
90 0
|
Shell Perl Linux
去掉Enter字符(\r)的几个方法
数据:test.txt: f1:f2:f3:0#1 Shell:   #!/bin/bash while read line do echo $line result1=$(echo $line|awk -F ':' '{print $4}' ) echo $re...
1367 0
单词替换,现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。
给定一个字符串 aa,请你按照下面的要求输出字符串 bb。 给定字符串 aa 的第一个字符的 ASCII 值加第二个字符的 ASCII 值,得到 bb 的第一个字符; 给定字符串 aa 的第二个字符的 ASCII 值加第三个字符的 ASCII 值,得到 bb 的第二个字符; …
128 0
|
开发工具
输入一行字符串将其中的单词替换成另一单词
输入一行字符串将其中的单词替换成另一单词
236 0
|
PHP
PHP面试题:对于用户输入一串字符串$string,要求$string中只能包含大于0的数字和英文逗号,请用正则 表达式验证,对于不符合要求的$string返回出错信息
PHP面试题:对于用户输入一串字符串$string,要求$string中只能包含大于0的数字和英文逗号,请用正则 表达式验证,对于不符合要求的$string返回出错信息
149 0
|
Ubuntu 安全 Unix
写代码注意了,打死都不要用 User 这个单词
当你意识到你在项目开始时做的轻量、简单的设想竟然完全错了时,你已经用了六个月的时间投入到这个项目上。