回顾有史以来最糟糕的一段代码

2020-08-02 10:52:42

有一个意大利语的Facebook页面叫做“Il Programmatore di Merda”(可以翻译成“差劲的程序员”)。我喜欢那一页。

他们经常分享关于编程的垃圾代码和迷因,但今天我看到了一些相当令人难以置信的事情:

这里有这么多错误的东西,我不知从何说起。如果你是初级开发人员,这篇文章将帮助你理解上面代码中写的一些非常糟糕的错误。

让我们写下上面的代码,以便我们可以讨论一下:

<;script>;函数AuthenticateUser(用户名,密码){var account=apiService。SQL(";SELECT*FROM USERS&34;);for(var i=0;I<;Accounts)。长度;i++){var account=Accounts[i];if(Account.。用户名=用户名&;&;帐户。Password=password){return true;}}if(";true";=";true";){return false;}}$(';#login';)。单击(function(){var username=$(";#username";))。Val();var password=$(";#password";)。Val();var Authenticated=AuthenticateUser(用户名,密码);IF(Authenticated=true){$.。Cookie(';LogggedIn';,';yes';,{Expires:1});}Else If(Authenticated=false){$(";ERROR_MESSAGE";)。Show(LogInFailed);}});<;/script>;

好吧,我真的不知道从何说起。让我们将上述错误分为三类:

我们非常确定下面的代码正在客户端运行,因为它被包装在两个<;script>;标记之间(而且使用的是jQuery)。不要误会我的意思,即使在服务器端也会很糟糕,但是在客户机上运行该代码会将您的数据库暴露给…。所有人。

函数AuthenticateUser(用户名,密码){var account=apiService。SQL(";SELECT*FROM USERS&34;);for(var i=0;I<;Accounts)。长度;i++){var account=Accounts[i];if(Account.。用户名=用户名&;&;帐户。Password=password){return true;}}if(";true";=";true";){return false;}}

我们在某个地方有一个名为apiServices的函数,它公开了一个.sql方法,您可以在其中对数据库运行SQL查询。这意味着如果您在承载上述代码的网页上打开控制台,您将能够生成各种查询。

并且它将使用它们自己的API返回它们的数据库表的完整列表。但是,嘿,好吧,让我们假装这不是一个真正的问题。但看看这个:

所以你是说你不用散列就能保存所有密码?走得好!现在,我可以将调试器附加到Chrome控制台,并查看每个用户的密码。我还相当肯定,有很高比例的用户在社交网络、电子邮件服务、银行账户等方面使用相同的用户名/密码元组。

还有一个问题是他们如何尝试设置LogggedIn Cookie:

因此,他们基本上使用jQuery来设置cookie,该cookie告诉Web应用程序用户是否经过身份验证。

如果您需要存储此类信息,Cookie是最常见的选择,这没问题!但是使用JavaScript设置它们意味着您不能设置httpOnly属性,因此每个恶意脚本都将访问您的cookie。

是的,我知道,他们只是存储了一个键值,比如登录:是的,所以情况并非如此,但这是非常糟糕的做法。

此外,打开我的Chrome控制台,我总是可以输入$.cookie(#39;LogggedIn';,';yes';,{Expires:1000000000000});而且我将永远保持登录状态,甚至没有帐户。

要说的事情太多了,时间却不多了。显然,AuthenticateUser函数是纯粹的垃圾,它显示出一些基本编程知识的缺乏。

函数AuthenticateUser(用户名,密码){var account=apiService。SQL(";SELECT*FROM USERS&34;);for(var i=0;I<;Accounts)。长度;i++){var account=Accounts[i];if(Account.。用户名=用户名&;&;帐户。Password=password){return true;}}if(";true";=";true";){return false;}}。

与其选择数据库中的每个用户,为什么他/她不只选择具有给定用户名和给定密码的用户呢?如果他/她在该数据库中有数百万用户怎么办?

我以前说过,我再说一遍,为什么他们不在数据库中散列密码?

让我们继续讨论AuthenticateUser的返回值。就我所见,它接受两个String类型的参数并返回单个布尔值。

对于(var i=0;i;lt;帐户。长度;i++){var account=Accounts[i];if(Account.。用户名=用户名&;&;帐户。Password=Password){返回true;}}。

“是否存在用户名为X、密码为Y的用户?是的,所以我将返回true“。但是这个:

这完全说不通。为什么在没有这个始终为真的条件的情况下,此函数不返回FALSE?

$(#39;#LOGIN';)。单击(function(){var username=$(";#username";))。Val();var password=$(";#password";)。Val();var Authenticated=AuthenticateUser(用户名,密码);IF(Authenticated=true){$.。Cookie(';LogggedIn';,';yes';,{Expires:1});}Else If(Authenticated=false){$(";ERROR_MESSAGE";)。Show(LogInFailed);}});

它使用jQuery取值的部分没有问题。问题是它是如何处理登录cookie的。

我们之前谈过,我只需打开Chrome控制台,输入$.cookie(';loggedin';,';yes';,{expres:1});就可以保持一天的身份验证,甚至不需要帐户。

那么,这个网页怎么会知道我是谁呢?也许它只是在用户名/密码身份验证下显示一些私人内容,因此不会显示任何个人数据。没人会知道的。

可能是整个代码中不太重要的部分,但我们可以清楚地看到,这个开发人员复制/粘贴了一些取自某个网站的代码。

这看起来可能并不重要,但实际上它告诉我们,开发人员可能从StackOverflow复制了一些代码,甚至没有遵循整个代码库的通用样式指南进行重写。当然,这是一个小问题,但它表明开发人员并不真正关心代码是如何工作的,它只是希望代码以某种方式工作。

不要误会我的意思,我每天都会在谷歌上搜索东西,但更重要的是要了解(例如)如何设置cookie,而不是仅仅为了让它正常工作而复制和粘贴一些东西。如果由于某种原因整个过程破裂了怎么办?您如何知道脚本的哪一部分不起作用?

我绝对肯定上面的代码是假的。这是我第一次看到同步SQL查询:

VAR帐户=apiService。SQL(";SELECT*FROM Users";,(err,res)=>;{Console.。Log(Err);//一些错误控制台。Log(Res);//查询结果});

即使apiService.sql同步返回值(我对此表示怀疑),它也必须在内部打开到数据库的连接、进行查询并返回响应,这(正如您可能已经猜到的)不可能是同步的。

但是,即使上面的代码不是假的,我也确信它是由初级开发人员编写的。在我成为开发人员的头几周里,我非常肯定我为我的老公司写了这么糟糕的代码(对不起:D)。

这不是初级开发人员的错误。让我们假设上面的代码是真实的。这里的初级开发人员正在尽最大努力使其正常工作。他/她还没有学会如何正确处理SQL查询、cookie和其他东西,这完全没问题!

高级开发人员应该提供某种形式的指导,以确保初级开发人员能够理解他们的错误,这样的糟糕代码不会投入生产。

我确信,有些公司并不真正关心他们正在发布的代码。它能解决问题吗?部署它。它是不是出自初级开发人员之手,甚至没有得到高级开发人员的批准?部署它。