使您的应用程序更专业的特性/功能?编码爱好马

Features/functions that make your app more professional? Coding hobbyhorses

提问人: 提问时间:9/27/2010 最后编辑:8 revs, 3 users 99%mario 更新时间:2/5/2012 访问量:4049

问:

已锁定。这个问题及其答案被锁定,因为这个问题偏离了主题,但具有历史意义。它目前不接受新的答案或交互。

您在 PHP Web 应用程序中实现(如何)哪些功能,因为 你认为它在某种程度上“更专业”?或者你有个人的吹毛求疵 和代码爱好,特别是可能很重要的小事? 你花了大量的时间在哪些不愉快的代码或次要功能上来做对

.

Q&A 插图的编码爱好示例:

不在数据库中的配置数据:应用程序数据 != 配置数据,其中 也是一个必要性和效率的问题。

URL 修复:通过附加尾部斜杠来规范化所有网址,即使从技术上讲不是必需的。

人类可读的 cookie:为了数据隐私,我尽量避免使用不透明的会话/数据库句柄(用于用户选项,而不是授权使用)。

内容协商:对简单的变体有意义 例如.RSS和 Atom 格式之间。但我看到它很少使用。

UI 中没有数据库 ID:避免将数据库内部代理项密钥泄漏到 URL 中。使用 ORM,db-internal 密钥甚至不必泄漏到业务逻辑中。

.

提示(非规则)

  • 那么,您认为哪些功能使您的 Web 应用程序高于平均水平?
  • 为什么它不常见?
  • 它是否使用户受益,但同样容易被忽视?
  • 更专业、更安全的编码建议非常切合主题。他们总是如此。
  • 这个问答的预期范围实际上是不常见/独特的功能,也可能是非标准和有争议的功能。令人着迷的大奖金。
  • 它还与恰好在PHP中实现的编码偏好和吹毛求疵有关。
  • 不要想得太大或太高。小功能也很重要。
  • 如果可行,请显示代码。
  • 然而,语法和编码风格/范式大多是偏离主题的。
  • 我们不要争论有用性或代码质量。这纯粹是一个特征和代码调查。

第一轮特征研究赏金:很难从众多好主意中选出一个。说实话,我只能将其缩小到五个最爱,并将决定权留给.这个话题绝对足够有趣,值得第二轮赏金。休息了一会儿。也许其他人会接管来完善范围。rand()

PHP的

评论

0赞 Marcelo Cantos 9/27/2010
WRT Config 不在数据库中,请使用 memcache,例如,五分钟的到期时间。一个更复杂的选项是,每当配置发生变化时,都会触摸“重新加载配置”页面;诀窍是确保触摸场中每个应用程序服务器实例上的页面(这就是我更喜欢 memcache 的原因)。
0赞 mario 9/27/2010
@Marcelo:你能把它作为答案发布吗?这是一种相当标准的解决方法/替代使用方法,仍然在问答范围内/有趣/更专业。
4赞 Bill Karwin 9/27/2010
这是一个很好的问题,但它属于 programmers.stackexchange.com,因为它不是一个有正确答案的具体问题。
0赞 mario 9/27/2010
@Bill Karwin:我对此非常不确定。程序员是关于人的。但这个问题是关于代码的。它非常开放。但这就是我把它做成社区维基的原因。也许它属于两者?(部分);}
4赞 Alix Axel 10/23/2010
尽管如此,您的问题并非特定于 PHP,您提到的所有特性/功能都可以在任何其他 Web 语言中实现。我仍然认为你应该重新标记,也许添加一个和标签。web-developmentbest-practices

答:

5赞 3 revsmario #1

以 Jus 为例: URL“修复”
对于 http-URL,我将路径片段视为强制性的,就像每个浏览器一样 确实如此。因此,我强调要“修复”用户输入和导入的数据,并始终添加 在显示或存储此类值之前,尾部斜杠到例如 http://example.org。 可能不是“超级专业”,但规范化 URL 通常会简化处理 以后和他们在一起。而且不知道,它只是看起来“更好”。

 $url = preg_replace("/^(http:..[-\w.\d]+)$/", "$1/", $url);

所以无论如何,我都会一直有价值观。 这并不能使你的HTML更符合标准,但这只是我的烦恼之一。http://example.org/

评论

0赞 Alix Axel 4/6/2012
+1,效率会更高。$url = sprintf('%s/', rtrim($url, '/'));
3赞 Marcelo Cantos #2

WRT Config 不在数据库中,请使用 memcache,例如,五分钟的到期时间。一个更复杂的选项是,每当配置发生变化时,都会触摸“重新加载配置”页面;诀窍是确保触摸场中每个应用程序服务器实例上的页面(这就是我更喜欢 memcache 的原因)。

评论

1赞 NikiC 10/24/2010
如果您不想设置 mamcached,只需使用 APC ;)
40赞 2 revs, 2 users 80%koen #3

文档

想象一下,你可以找到任何开源项目,无论有没有最新的文档,并感受到这对你认为它的专业程度的影响。

评论

2赞 NikiC 10/23/2010
+1 对于开源项目来说,这一点非常重要。未记录的项目使用起来很痛苦。我想为Mozilla或PHP做出贡献,但他们没有文档,因此我无法:(
13赞 mario 10/23/2010
还要注意反模式:冗长的phpDoc注释和自动生成的列表不能替代教学文档。
0赞 Pekka 10/30/2010
曾经问过一个问题,关于好的开发人员文档工具,这些工具产生了很好的反馈。
24赞 mykhal #4

对于专业的外观,非常重要的是干净和美观的图形设计。因为封面是现在最畅销的东西。可悲,但真实。具有漂亮代码和丑陋外观的 Web 应用程序不会引起太多关注。

评论

4赞 Bill 10/28/2010
这是许多优秀程序员失败的领域。尤其是在程序流程如何工作时。程序员总是确信他们写的东西是直观的,因为他们认为它是,通常是创造性偏见的有力案例。
4赞 Dlongnecker 10/28/2010
这并不像听起来那么肤浅。有些人会因为这么说而杀了我,但平面设计、UI 和 UX 往往是相关的。
3赞 slebetman 10/30/2010
是的!聘请一位真正的艺术家(或找一个志愿者——虽然这并不容易,但他们在版权方面有不同的心态)。哎呀,杰夫·阿特伍德(Jeff Atwood)自己也是这么说的:Stackoverflow的原始版本很糟糕,直到他们聘请了一位真正的艺术家来做设计。
1赞 Paul Sasik 10/30/2010
这不是悲伤,而是真的。这是现实的。好的 UI 不仅好看,而且直观且易于使用,仅这两个概念就很好。
6赞 Adam Casey #5

一致的编程风格、变量命名、支撑等。遵守编码标准(任何编码标准)。确保由不同人编写的文件看起来相同,这样维护代码就不需要知道是谁编写的。

评论

0赞 NikiC 10/23/2010
不确定零件是否正确。您应该使用用这种语言编写的大多数项目使用的编码风格。在 PHP 中,这将是 Zend 编码指南。(诚然,我并不严格遵守它们:()any coding standard
1赞 Adam Casey 10/24/2010
我不同意。每个商店的编码标准都不同。目标是使所有代码都与正在使用的代码匹配,从而简化维护。这适用于所有语言;我把PHP归为一类。例如,我们有一个强大的 C 编码标准,但没有针对 PHP 的标准。我们的 C 标准经过调整,因为它使我们的 SW 组更加一致。
0赞 El Yobo 10/24/2010
我和亚当在一起;任何标准(在合理范围内)都是可以的,重要的是标准存在并且它被强制执行(例如,使用 PHP 代码嗅探器等)。
0赞 NikiC 10/24/2010
@Adam:我确实认为编码风格应该在项目中标准化。我只是不认为你不能为此选择一些你个人喜欢的任意标准,而是语言中最常见的标准。这样,不仅项目内的编码是一致的,而且在多个项目之间也是一致的。如果你使用 Zend 编码标准,你可以非常确定任何人都可以在不学习一些新的编码风格的情况下参与这个项目——仅仅因为它是最流行的标准。但也许我在这一点上太严格了。
1赞 mario 10/24/2010
我在这里的理解是“任何编码标准”意味着简单地选择或继承一个并坚持下去。适当的建议。就我个人而言,我会避免模仿 Java 的货物崇拜编码风格。但无论如何,这也是题外话,因为这个问答不是关于编码风格的。从技术意义上讲,这不是一个功能。
12赞 2 revsSlomojo #6

密码强度/匹配

在注册或更改密码时,以交互方式通知用户其密码的强度弱点。当他们的确认匹配时,还要通知他们。

实时表单验证

与密码一样,表单条目的实时验证比允许用户在知道自己犯了错误或省略他们跳过的必填字段之前完成整个表单要少得多。

具有友好异常/错误处理的防御性编程

永远不要使用隐晦的错误消息,并且通常参考您可以找到的最佳案例示例,以获取友好的错误消息。在最好的情况下,这通常需要一位才华横溢的撰稿人负责保持良好的语气等。

这与可靠的异常处理和良好的防御编程密切相关。

《防御设计》是一本关于这个主题的相当不错的书。

31赞 6 revs, 3 users 86%NikiC #7

注意安全,尤其是用户的私人数据。

使用强哈希(如 bcrypt)存储密码(参见 crypt 文档):

// generating hash
// read up how $costParameter and $salt look like in the crypt() docs
$hash = crypt($password, '$2a$' . $costParameter . '$' . $salt . '$');

// checking if password is correct
if (crypt($whatTheUserEntered, $hash) == $hash) {
    // correct password
}

$salt不应为静态值。对于每个用户来说,它应该是不同的。

评论

2赞 Xeoncross 10/28/2010
+1 表示多次迭代,这会增加暴力破解所需的时间。
8赞 mway 10/28/2010
$salt也应该是用户无法更改的内容,因为这会使他们的密码失效,他们必须更改新密码。所以,如果用户名是永久性的,那就太好了;如果没有,可能是他们的行 ID、创建时间等。
0赞 Jimmy 10/30/2010
我更喜欢随机盐,而不是可以推断的东西,例如用户名或任何用户特定的详细信息
2赞 NikiC 11/2/2010
@Logan Bailey:显然它不会增加熵。该技术称为拉伸,用于使破解哈希更加耗时。在您的服务器上进行数千次哈希处理可以忽略不计,因为您很少这样做,但它会在很大程度上减慢攻击者需要字典/...攻击哈希;)PS:不,字典攻击不会被盐阻止。它只能防止攻击者不能对数据库中的所有哈希值使用一个彩虹表,但必须为每个密码生成大量哈希值;)
3赞 Dereleased 11/4/2010
为什么不使用php的内置函数呢?您可以使用像 bcrypt/eksBlowfish、SHA-256 或 SHA-512 这样的强密码,它完全抽象了实现细节。crypt()
8赞 Baju #8

延续点

示例:您提交了一个表单,您被重定向,现在登录页面应该保留通知。大多数站点只是将该通知存储在会话中。这意味着:接下来将访问的任何页面都将显示该消息。在大多数情况下没问题,但对我来说真的很混乱。我认为会话是针对会话数据的,而不是下一个请求数据。

我的解决方案:创建一个数组,将数据(通知等)写入其中,使用 sessionid + 唯一标识符将其保存在 memcache 中,然后在重定向上添加参数 __continuation={该唯一标识符}。然后,下一页再次加载该数据并对其进行处理。

当您想要拥有更多数据而不仅仅是一条短消息时,这将变得更加方便。

问题?

评论

0赞 mario 10/23/2010
我使用了一个简单的表单重定向/登录页面方案。但我明白你的意思。对于非静态消息和自定义消息,您需要适当的存储。诚然,会话存储本身不能用作数据转储或消息队列。?msgid=5
1赞 ssokolow 10/29/2010
对于无论如何都需要 Javascript 的网站来说,最简单的解决方案可能是使用 HTML5 sessionStorage 和某种后备。(sessionStorage 类似于 localStorage,但属于制表符本地,不会在浏览器重启后持续存在)
2赞 2 revsmario #9

我知道这是可怕的代码,应该被否决。只是想举个例子,内容协商实际上很容易实现。

function q_order($src) {
    $src = str_replace(",", ";q=0.99,", "$src;last;q=0.975");   // inject placeholder values
    foreach (explode(",", $src) as $prt) {   // split entries
        $q[trim(substr($prt, 0, strpos($prt, ";")))]   // append TOKEN until ";" 
        = floatval(substr($prt, strpos($prt, "q=") + 2));  // and first float after "q="
    }  
   arsort($q);
   return($q);
}   

这允许对HTTP_ACCEPT标头进行快速排序,这对于在 RSS 和 Atom 源格式之间自动交替非常有用。或者只是为了设置默认语言。(无论如何,您经常需要语言标志/链接,但这比仅默认为英语要好。

$lang = q_order($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
if ($lang["de"] >= $lang["en"]) { ...
4赞 2 revsSrikar Appal #10

任何 2.0 Web 应用程序都应该具备的重要内容之一是 -

  1. 搜索 - 无论是全文搜索、关键字搜索、自动建议还是(最新的)实时搜索。如果没有这个功能,当我访问任何网站(尤其是那些对搜索引擎关闭的网站)时,我会感到窒息。对于任何现代 2.0 站点 PHP,无论是否都必须具备。
  2. MVC 框架 -由于这与 web-dev 有关(不依赖于 PHP),因此 Model-View-Controller 框架是必须的。由于过多的代码库和更快的迭代周期,适当的结构是防止未来麻烦和无法追踪的错误所必需的。
  3. 阿贾克斯 -需要我谈谈这个:)它改变了我们大多数人浏览网站的方式。AJAX使网站具有很酷的功能。
  4. 调试信息 -这适用于应用程序崩溃时的情况。你如何找到问题所在?你们维护日志吗?您能否从日志中将问题追溯到其来源(发生数小时后)?您应该让日志有多详细?
  5. 缩小的 Javascript 和 CSS -减少加载时间,使网站更加活泼,从而使用户在浏览网站时感觉更舒适。
  6. 缓存-再次极大地增加了用户的感知响应时间,从而使网站更加“专业”。

评论

0赞 mario 10/23/2010
好点。但是让我很快不同意“MVC”部分。我正在维护 php 框架矩阵,并且没有 MVC 框架。这是用词不当。你不能在 Web 应用程序中拥有真正的 MVC(除非使用像 Capuccino 这样的全 AJAX 框架)。大多数 PHP 实现要么是 PMVC,要么是更接近 MVP。无论如何,它主要是编码风格,而不是真正的功能。
0赞 Srikar Appalaraju 10/24/2010
同意这是一种编码风格。MVC 模式可供编码人员遵循,以便维护变得更加容易。很容易在一个领域之间失去区别,并将其与其他领域混为一谈。但是,如果一个人煞费苦心地遵循这个框架,从长远来看,它可能会对他/她有所帮助。这不算是更“专业”的应用编码吗?也许不是作为“功能”,但绝对是一种实践......
0赞 balupton 10/26/2010
@movieyoda “AJAX 支持网站是一个很酷的功能”——让它看起来你过度使用它只是因为它“很酷”,而不是有用。例如,你的网站是否正确地进行了验证,失败的ajax请求的错误报告,可抓取的ajax,优雅的ajax,请求失败时的好错误 - 总的来说,这些东西中几乎没有任何一个被ajax覆盖,而且对所有人来说都非常罕见 - 因为这样的AJAX实现很少“酷”。
0赞 Srikar Appalaraju 10/27/2010
@balupton我再次不同意。如果有人要去 AJAX,这意味着他会做你提到的所有其他事情。基本上让用户处于循环中。什么样的程序员会写代码而不处理错误?你说的更具体地针对特定的程序员。我要说的是,这项技术在网络上有着广阔的未来。所以我想你不使用 GMail 或 Google Reader?
0赞 balupton 10/27/2010
问题是关于专业精神。AJAX != 专业精神。仅仅因为你使用Ajax是因为它很酷,并不能让你或你的网站更专业。如果问题是关于很酷的技术,那么你会得到+1
22赞 4 revsPekka 웃 #11

运行状况检查

一系列预配置的测试,用于确定 Web 应用程序或网站的基本“运行状况”,可以随时(由管理员/网站所有者)查看,显示以下内容:

  • 数据库服务器是否可访问?
  • 必要的文件和目录是否可写?
  • 所有的数据结构都是理智和完整的吗?
  • 所有页面/对话框/查询是否正确显示?
  • 是否有足够的可用磁盘空间?
  • 等等等等。

一个简单的状态页面以绿色、橙色或红色背景显示系统的当前“运行状况”。

这与单元测试的不同之处在于,它处理的是“真实世界”环境的运行状况,而不是抽象的代码完整性。

运行状况检查还使将应用程序迁移到另一台服务器变得容易。

我已经在几个需要持续监控的项目中实现了这一点;我计划在今年的某个时候把它做成一个小型的、可扩展的“插入式”开源应用程序,可以在各种 Web 应用程序甚至网站中使用。非常欢迎参与和投入 - 有关更多详细信息,请参阅相关的 SO 问题

评论

3赞 mario 10/24/2010
关于这一点的好奇之处在于,所有主要的PHP应用程序都附带了执行大多数检查的安装程序。但它在管理后端中普遍缺失。
1赞 Pekka 10/24/2010
@mario是的,我也从来不明白这一点。
12赞 2 revs, 2 users 82%Crozin #12

编写易于维护的代码。在开始编写之前,请多想几遍对象的界面。添加许多事件触发器,即使您现在不需要它们。它们在功能中可能很有用。

编写代码,就好像它是外部库一样。即使您正在处理商业、封闭的应用程序,也应将其视为开源项目。想想其他用户,他们可能希望在不更改现有代码的情况下更改现有代码的行为。当你使用类型提示时,你可能应该检查接口而不是类,所以:

public function add(Storable $resource);    # Good
public function add(SessionStore $session); # Bad

不要使用全局命名空间和“全局功能”。定义全局常量或使用(而不是使用 注册另一个自动加载器)是一种不好的做法。__autoload()spl_autoload_register()

使用第三方代码。那里有很多图书馆。大多数时候,开发自己的ORM或Mailer是没有意义的。它减少了开发应用程序所需的时间,>降低了成本。

创建 API 文档。我认为不需要任何解释。

使代码看起来干净,并保留一些编码约定。

不要创建无用的页面。没有什么比 404 未找到页面更烦人的了,仅此而已,只是一个大的 404 未找到信息。您可能应该为每个资源提供几个未找到的页面。因此,如果我访问并且此类资源不存在,除非我们很抱歉,该视频不存在或已被删除。 添加如下内容: 最近的视频, 也许您正在寻找:“how to dace”、“swimming: abc”(标题类似于标题形式的视频 URL(如何游泳))等。/video/123/how-to-swim

允许用户自定义网站。想象一下,您有一个包含多个“框”的主页:最近的视频、最近的照片、最近的活跃主题、新闻、推广的画廊等。允许用户隐藏其中一些,更改他们的顺序 - 有人可能对照片和视频更感兴趣,而不是新闻和线程,所以他/她可能希望将它们放在页面顶部,其他人可能有不同的偏好,可能希望有不同的顺序。为每个框添加首选项,例如:“显示:5、10、20 个最近的视频”。

评论

0赞 mario 10/23/2010
嗯,我需要取消这个答案的资格。这些都是提高应用程序质量的非常有用的建议。但它在这里的编码风格上离题太远了。很好的提醒,但似乎只有最后两点是关于特性/功能的主题。
2赞 2 revsmario #13

配置数据不在数据库中:应用程序数据属于数据库。 但配置设置没有。为什么?

  • 在每个 PHP 请求上查询数据库的运行时选项效率不高。
  • 设置不会每天更改,静态存储对于大多数用例来说就足够了。
  • 数据库配置文件之间的差异,但在数据库中拥有其余的运行时选项似乎很愚蠢。
  • IMO 这通常是由于懒惰而完成的,因为安全地设置和修改文件 (ini) 存储比另一个 SQL 表更复杂。
  • 例外情况是,如果没有数据库存储,则无法管理用户设置和每个域的配置。

虽然在实践中很少需要,但实际上我确实希望我的用户能够编辑运行时配置(每年一次)。因此,实际上,我在配置文件修改功能上花费的时间比数据库所需的时间还要多。优点:比 SQL 配置表更容易备份和版本控制。

缺点:如果访问/存档/版本控制不是问题,那么如果与 APC 或 memcached(用于高效访问)结合使用,则 SQL 可以很好地存储配置。缓存文件也是一种可能的解决方案。

0赞 3 revsmario #14

人类可读的 cookie
我个人认为,仅仅因为变量更容易用 PHP 存储在那里,总是求助于 SESSION 有点不艺术。

从技术上讲,会话 ID 通常也是 Cookie,但不是人类可读和不透明的存储句柄。因此,相反,如果它是简单的用户首选项(不是自动化的东西),我喜欢发送可读的 cookie 名称和值,例如 或 .product_order=descfav_background=orange

通常我也会求助于会议。但是对于我关心数据隐私(即用户权利)的个人项目,我忍受了所有的缺点:

  • 为多个 Cookie 提供更多的微观管理开销。
  • 分别对每个 cookie 进行有效性检查,因为它都成为用户输入。
  • 可能需要定义额外的过期 Cookie 或以其他方式随机续订。(由于我发现 2038 cookie 到期时间同样不合群,并且只使用适当的时间。
  • 不能用于任何与授权相关的内容,而只能用于用户和显示选项。
  • 我认为识别真实 cookie 和会话 cookie 之间的语义差异很重要。但是,如果几乎没有人看到它,那么在这里要小心吗?

然而,这让我的数据隐私大脑部分感到高兴。对于某些用例,这是一个简单而简单的不费吹灰之力的事情。

评论

2赞 NikiC 10/24/2010
-1 好吧,我认为你所做的,是不行的。会话 cookie,名称为 md5 字符串,值为 md5,需要在每个连接上传输 9+1+32=42 个字符。现在想象一下,你有十个 cookie,而不是这个会话 cookie。这已经是 400 个字符了。在一个大型应用程序中,您通常不会只有 10 个首选项......PHPSESSID
0赞 mario 10/24/2010
优点和缺点。对于超过 10 个饼干,我不会走那条路。但对于一到三个用户选项,这是最佳方式。此外,会话 cookie 绝对不是 RESTful,而原样的 Cookie 数据很可能有资格作为请求元信息。
0赞 NikiC 10/27/2010
@mario:谁关心 REST?老实说,访问网站的人想要 a) 漂亮的设计 b) 页面的快速加载和 c) 好的内容。所以谁在乎 REST - 没有人。
1赞 mario 10/27/2010
是的。没有人关心 REST。没有人关心数据隐私/用户权利。这正是本次问答的范围。特别是对于很少有php程序员甚至更少的用户关心的事情。
0赞 NikiC 10/28/2010
好吧,我非常关心用户数据隐私。但是,恕我直言,将这些数据存储在 cookie 中而不是存储在服务器上的本地文件中并不能提高安全性。普通用户的计算机通常比您的服务器安全得多,因此可能更容易受到损害。因此,我认为有人从浏览器 cookie 中获取数据的可能性比他从服务器会话文件中窃取数据的可能性要高得多。特别是如果这些文件是加密的(Suhosin)。
5赞 mario #15

UI
中没有数据库 ID 大多数数据库对象都是使用某些代理键枚举的。我做什么 认为看起来不时尚(有时可能是一个安全陷阱)正在将这些泄漏到 UI 中,就像在 URL 中一样。将任何占用更改为 .对于数据库来说,查找 ID 或名称几乎没有区别。所以这不是关于SEO的愚蠢,而是关于一个华丽的外表
user.php?id=37310843user.php?name=title

  • 有了适当的 ORM,这些数据库内部 ID 甚至不必泄漏到应用程序逻辑中。
  • 展示维基百科:想象一下他们使用代理键而不是页面标题。(见 CoWiki)
  • 由于外部链接始终指向标识内容,因此仍应避免使用代理键。如果它足够重要,可以进行确切的分配,那么无论如何都应该使用 GUID。
11赞 12 revsErgo Summary #16

添加更多(较少面向 PHP)的点,这将增强用户体验并使您的应用程序更专业,但会处理后端:

良好的压缩/缩小
通常,Web 应用在加载时和使用过程中都会发送大量请求。缩小可以帮助减少初始加载权重,CSS 精灵和 GZipping 内容的使用也是如此。帮助您简化和尽可能快速地制作应用程序的一个好方法是 Yahoo 的 Firefox Firebug 扩展的 YSlow 插件:

萤火虫:http://getfirebug.com/

YSlow:http://developer.yahoo.com/yslow/

另外,一些好的做法:http://developer.yahoo.com/performance/rules.html

YSlow 将帮助您确定如何真正使您的应用程序整洁、快速和干净。我还推荐 PHP Minify 来处理大部分文件压缩,它是一个非常强大的工具:

PHP缩小:http://code.google.com/p/minify/

此外,获得 Firebug 的另一个原因是它在开发任何 Web 应用程序时提供的巨大好处,尤其是确定应用程序的安全性,因为在操作过程中您可以跟踪创建的数据流。

混淆
---拆分为下面更详细的答案

Apache重写的
好用 除了提供干净的URL以增强浏览体验和给人以逻辑归档内容的印象的基本好处外,一个好的.htaccess文件还可以为您的网站添加额外的安全层,压缩内容服务器端并添加额外的标识符(例如E-Tags,尽管它们的好处是有争议的)。每个 Web 应用程序也应该有一个写得很好的 .htaccess。

兼容性/验证
我总是强烈敦促任何开发人员尽最大努力(合理)确保他们所有的输出代码都是有效的、注释的、逻辑的和干净的。W3C 不仅明确规范了 HTML,还明确规范了 Web 应用程序应该如何运行。遵循他们的指导,以提高你所写任何内容的兼容性,以确保它以你所设想的方式适用于每个人。

一些很棒的工具:

HTML 验证器:http://validator.w3.org/

其他验证:http://validator.w3.org/unicorn/

需要注意的一些规格:

W3C Web 应用程序 (WebApps) 工作组:http://www.w3.org/2008/webapps/

W3C 辅助功能指南:http://www.w3.org/WAI/guid-tech.html

W3C WAI-ARIA 计划:http://www.w3.org/WAI/intro/aria.php

在 Javascript 方面,JS lint 是一个很好的工具,可以确保 JS 中的任何错误(检查时可能不会影响性能)被消除:

JSLint:http://www.jslint.com/

通过代理,为了帮助开发,美化的 JS 可以帮助你更好地构建代码以进行开发、预缩小:http://jsbeautifier.org/

当然是美化的PHP......http://beta.phpformatter.com/

最后 - 少一点黑白
的人性化

也许生产基于 Web 的应用程序的最大好处之一是它们可以提供连接,不仅在用户之间(为了鼓励协作工作),而且在用户和应用程序本身以及负责其持续开发和维护的人之间。

如果你想到像 37 Signals 这样的项目,其中一个吸引人的因素是它们给用户的感觉是项目(代码)本身已经人性化并具有个性,有助于吸引用户并与应用程序相关联,鼓励享受使用和与他人交流。我并不是说这个应用程序看起来“活着”,而是说它感觉更“平易近人”,用户可以“认同”它。

然而,这只是人性化硬币的一面,它几乎要让用户对应用程序/代码/框架/体验产生“共鸣,从而鼓励他们使用它。另一方面是打破应用程序与其背后的人之间的界限。

我们都喜欢了解我们使用的东西背后的人、人等——因为我们从他们那里传授了很多信息,并且经常不合逻辑地将其应用于应用程序本身,实际上是我们对它的“喜欢”(即像史蒂夫乔布斯,购买苹果等。虽然诚然是一个任性的例子)。拥有一条我们可以在遇到困难时联系真人的途径是一个简单的步骤,拥有开发人员博客、新闻流等——围绕应用程序构建一个人性化的元宇宙会给它带来可信度,并感觉它可能大于其各部分的总和。

诚然,人性化可能既不在这里也不在那里——而且它当然很难构建(就像不同的人有不同的朋友一样),但开发人员可以通过任何方式打磨一个更临床的外科手术应用程序的边缘,让它对日常用户来说更舒适、更平易近人、更有趣,这是我书中的赢家。

评论

1赞 mario 10/26/2010
赞成,尽管我不同意反开源的混淆(通常会导致虚假的安全感)。验证和 WAI/ARIA 合规性是一个很好的点。
0赞 Industrial 10/26/2010
您是否愿意展示混淆例程的更多细节?
0赞 SW4 10/26/2010
我同意反开源评论的混淆,也许它只适合某些应用程序(我主要为金融服务行业编写代码,在这种情况下,它增加了一层额外的保护——即使是最小的,对客户端 IP 以及应用程序的攻击能力)
1赞 SW4 10/26/2010
关于混淆例程,我非常乐意阐明,尽管不想弄乱问题 - 我很乐意 PM 您或在其他地方回答,因为您更喜欢:)
1赞 Aaron Hathaway 10/28/2010
我想了解更多关于混淆的信息,请;)
0赞 Scott #17

测试

我不是说“健康检查”应用程序的快速脚本,这些脚本大多毫无价值。如果你的大部分或全部代码都经过了强大的测试,你和你的客户就更有可能从精心设计的敏捷代码中受益。

可读性

其他人将使用您的代码,您稍后将对其进行更新。如果你看不懂你的代码,它就毫无价值(顺便说一句,注释不算在内)。变量应正确命名,上下文到上下文的流程应易于识别。

for ( $i=0; $i < count($myList); $i++)  // obviously an index
foreach ( $k as $a => $b ) // wtf?
foreach ( $definitions as $word => $definition ) // better
3赞 2 revsbalupton #18

PHP 中的 delve 函数允许您:

$a = delve($array,'a.b.c.d','default'); // $a->b['c']->a
$b = delve($object,'a.b.c.d','default'); // $a->b['c']->a

如果没有这个,你将不得不一直做痛苦的 issets 和 empty 以及数据类型检查。这是迄今为止我最喜欢的功能。

关于使代码更专业的是单元测试,文档版本控制和先做(然后如果你做不到,那就恢复到堆栈溢出)。

/**
 * Delve into an array or object to return the value of a set of keys
 * @version 1, December 24, 2009
 * @param mixed $holder
 * @param mixed $keys
 * @param mixed $default
 * @return mixed
 * @package balphp
 * @author Benjamin "balupton" Lupton <[email protected]> - {@link http://www.balupton.com/}
 * @copyright Copyright (c) 2009-2010, Benjamin Arthur Lupton - {@link http://www.balupton.com/}
 * @license http://www.gnu.org/licenses/agpl.html GNU Affero General Public License
 */
function delve ( $holder, $keys, $default = null) {
    # Prepare
    $result = null;
    $end = false;

    # Prepare Keys
    ensure_keys($keys, $holder);

    # Handle
    $key = array_shift($keys);
    if ( $key === null ) {
        # Reched the end of our key array, so holder must be what we want
        $result = $holder;
        $end = true;
    } else {
        switch ( gettype($holder) ) {
            case 'array':
                if ( array_key_exists($key, $holder) ) {
                    # We exist, so recurse
                    $result = delve($holder[$key], $keys, $default);
                } else {
                    $end = true;
                }
                break;

            case 'object':
                if (
                    /* Already accessible via normal object means */
                    isset($holder->$key)
                    /* Is Doctrine Record */
                    ||  (   ($holder instanceOf Doctrine_Record)
                            &&  ($holder->hasAccessor($key)
                                    ||  $holder->getTable()->hasField($key)
                                    ||  ($holder->hasRelation($key) && (!empty($holder->$key) || $holder->refreshRelated($key) /* < returns null, hence the OR and extra check > */ || isset($holder->$key)) ) // && $holder->$key->exists())
                                )
                        )
                    /* Is normal object */
                    ||  (   !($holder instanceOf Doctrine_Record)
                            &&  method_exists($holder, 'get')
                            &&  $holder->get($key) !== null
                        )
                ) {
                    # We exist, so recurse
                    $result = delve($holder->$key, $keys, $default);
                } else {
                    $end = true;
                }
                break;

            default:
                $end = true;
                break;
        }
    }

    # Check Default
    if ( $end && $result === null ) {
        $result = $default;
    }

    # Done
    return $result;
}

完整文件(和库)可在此处获得: http://github.com/balupton/balphp/blob/master/lib/core/functions/_arrays.funcs.php

评论

0赞 mario 10/26/2010
哦,非常适合树遍历和深度嵌套的对象。您的许可证要求您也向我们展示 ensure_keys() 功能!:}
0赞 balupton 10/26/2010
呵呵,谢谢!:D实际上,作为版权所有者,我没有义务做任何事情,如果您要修改任何代码,但是我可以向您请求相同的特权 - 您可以拒绝并停止使用,或提供并继续使用;-)无论如何,我已经添加了链接,因为整个库都是开源的,供所有人欣赏:-)
0赞 Alix Axel 6/6/2011
@balupton:为什么会有这么多的代码和递归?是不是和 github.com/alixaxel/phunction/blob/ 很相似......
0赞 balupton 6/6/2011
@Alix - 您链接的值函数似乎只扫描数组的第一级,delve 中的递归是我们可以做的,而您链接的那个只是 for 然后必须再次调用。a.b.ca.bb.c
0赞 Alix Axel 6/6/2011
@balupton:不,它贯穿整个数组(或对象属性),唯一的区别似乎是 ur 是一个点分隔的字符串,而我的是一个字符串或一维数组,可以使用 和 转换为您的符号(反之亦然)。=)$keysimplode()explode()
1赞 SW4 #19

你有个人的吹毛求疵和代码吗 爱好马,特别是小东西 这可能算数吗?哪个不咸不香 代码或次要功能 花费过多的时间 做对了吗?

正确引用数组键

任何非数字数组键(即不是索引)都应该用单引号括起来,以确保 PHP 在任何情况下都能正确处理它,并且在大多数好的代码编辑器中都能检测到语法。例如:

$array['key'];

$array[key];

需要/包含一次

总是问问自己为什么要使用require_once和include_once。大多数时候,这是为了防止复制您可能已经或可能尚未提取的代码 - 如果这是可能的,您真的以最有效和最有效的方式编写了 PHP 吗?

缓冲输出,用于清洁加载和提高速度

添加:

ob_start('ob_gzhandler'); 

到脚本的开头,以及:

ob_end_flush();

到最后,将压缩和缓冲脚本的输出,以便更快地加载它们,并且不会在提供内容时以增量方式显示。

预定义循环

每次运行循环时,都应在启动之前设置最大值。我看到太多引用函数的事件(尽管这被相当广泛地覆盖),即:

for($=0;$i<count($x);$i++){
// code
}

这意味着每次代码循环时都会运行 count 函数,效率低下。最好执行以下操作:

$stop=count($x);
for($=0;$i<$stop);$i++){
// code
}

正则表达式与 PHP 字符串/数字处理程序

减少对正则表达式的依赖 如果你正在处理字符串并且有一个 PHP 等价物,stripos、strncasecmp 和 strpbrk 更快。strtr 比 preg_replace快 5 倍左右。 ctype_alnum,ctype_alpha 和 ctype_digit 可用于帮助表单验证代替正则表达式。

清理工作区

完成数据库连接后,请始终关闭它们,并始终取消设置变量。如果完美主义的话,这是很好的实践。

一致使用报价

始终如一地使用单引号和双引号。即,如果您使用:

echo "this is a 'string' not a number";

然后不要使用:

echo 'this is a "string" not a number';

如果您需要颠倒顺序,请不要 - 保持不变并转义递归引号。此外,PHP 可以更好地处理用双引号封装的字符串,您可以在不需要连接的情况下封装变量。例如:

echo "this and $thisvariable here";
// instead of
echo 'this and '.$thisvariable.' here';

评论

0赞 mario 10/26/2010
所以,再投一票,然后;)虽然它接近编码风格,但我喜欢其中的一些建议,因为它们似乎基于事实偏好和增强经验。
1赞 NikiC 10/27/2010
我投了反对票,因为我认为这在很大程度上是题外话。此外,直接变量插值被认为是一种不好的做法。因此,您应该使用“代替”变体。此外,我不知道你应该在多大程度上使报价保持一致。例如,我通常只使用引号,因为它们不允许变量插值,并且引号内的任何 HTML 位置都不需要属性转义 ()。但是,如果我需要使用具有大量和很少的字符串,那么我认为我最好使用 NOWDOC 或双引号;)'"'"
-1赞 2 revsmario #20

密码劫持
我们最初在这里得到了一个答案,那就是支持和反用户安全。该建议是关于用户注册的,并使用提供的注册电子邮件与用户 SMTP/POP3(?) 服务器检查提供的密码,如果用户懒惰地重复使用他的电子邮件/POP3 帐户密码,则会给出一条粗鲁的错误消息。

显然,它被否决了,因为闯入用户的电子邮件帐户是值得怀疑的(即使意图显然是为了教育)。所以答案被删除了。但我喜欢对用户粗鲁的元概念,如果它有助于他的安全。

其次,我认为,虽然这个功能对于公共网站来说是一个法律上的错误功能(如果事先没有明确的警告或其他信息),但对于 Intranet Web 应用程序来说,这是一个非常可能的概念。我认为,对于公司内部的IT策略来说,确保密码在更敏感的系统中是唯一的,这甚至是一件很常见的事情。

评论

0赞 NikiC 10/27/2010
再次-1。我认为对某人无礼从来都不是一件好事。特别是如果这个人愿意为你的产品或服务付费。对他无礼,他可能会改变主意;)
0赞 Peter Schuetze 10/29/2010
我不确定您的概念是否适用于公司内部 IT 系统,因为安全策略通常禁止使用未分配给您的凭据(可审计性)。我希望公司更愿意使用身份和访问管理解决方案,允许您定义密码规则、关联差异系统的帐户以及定义对应用程序的访问规则。例如,这可以是 IBM 工具 Tivoly Directory Server (TDS)、Tivoly Access Manager (TAM) 和 Tivoly Identity Manager (TIM) 的组合。根据您的用例,您可能需要更多组件。
10赞 mario #21

无强制注册
这是日常 Web 应用程序的常见问题。强制帐户注册对用户不友好。如今,防止垃圾邮件和滥用是必要的。但它阻碍了采用。

我想每个人都听说过 Stackoverflow。它们不强制注册。您可以在没有帐户的情况下参与。它不是强迫注册,而是系统地鼓励注册。然而,主要的一点是,至少可以选择在承诺之前逐渐适应。

这是一个简单的概念。但这同样难以实现。很少可以使用临时和可选用户帐户,必须为此准备基本应用程序逻辑和数据库结构。无论实施工作如何,我相信这是一个重要且未被重视的功能。

评论

2赞 Alan Pearce 10/28/2010
网上商店是最糟糕的。有时,人们只是想买东西。
3赞 2 revs, 2 users 80%Ziplin #22

自动化单元测试

很重要,就像健康检查页面一样重要。一旦我的代码增长到 800 行以上,我就不记得我在第 100 行做了什么,我可能会在不知不觉中破坏它。

3赞 2 revs, 2 users 96%RobertPitt #23

注册表系统。

我之前已经多次谈到存储对象和范围问题,我所知道的克服这个问题的最好方法是使用带有 getter 和 setter 的 Static / Abstract 类,这可以帮助您在应用程序周围传输对象,并节省您修改类的麻烦,以便您可以专门导入对象以供使用。

该类可以像具有 2 个方法和 1 个数组的抽象静态类一样简单,这些是克服大范围问题的基本要素,而不会影响烤箱中的任何其他内容。

这是我所说的一个小例子:

abstract class Registry
{
    private static $objects = array();

    public static function set($name,$object)
    {
        self::$objects[$name] = $object;
    }

    public static function get($name)
    {
        return self::$objects[$name];
    }
}

看看这个类的简单性,没有什么可害怕的,没有什么可以让你修改你当前的框架/应用程序来采用这种方法,但如果你不确定它是如何工作的,让我给你一些例子

首先,假设我们有 ,并在您的包括您的库和核心框架代码中,但在启动时加载以下内容index.phpstartup.phpstartup.php

  • 数据库
  • 会期
  • 文件编写器
  • 输入
  • 输出

现在,如果您想将该对象用作在对象中记录的工具,您通常会调用一个变量,并在 Object 中使用 global 关键字FileWriterDatabase$FileWriterDatabase

但通过执行以下操作:

Registry::set('Database', new Database())
Registry::set('Session', new Session())
Registry::set('FileWriter', new FileWriter())
Registry::set('Input', new Input())
Registry::set('Output', new Output())

您将所有内容存储在您的对象中,因此让我们看一下我们的数据库对象/类Registry

class Database
{
    //..
    
    public function connect()
    {
        if(!$this->connected())
        {
            try
            {
                $this->connect();
            }catch(Exception $e)
            {
                Registry::get('FileWriter')->Write('db_logs',array($this,$e),'unable to connect to database');
            }
        }
    }
    
    //..
}

现在,正如你所看到的,注册表在类的范围内是可用的,而且它干净、安全,你不占用额外的变量或使用更多喜欢的代码,只是干净、简单和安全globalization

希望您喜欢阅读。

15赞 SamGoody #24

源代码管理。特别是 Git(虽然不是专门的 GitHub)

好吧,这并不少见。
但是,当我外包代码并取回一个整洁的存储库时,其中包含所有的历史和曲折,我印象远比一个装满 php 文件的文件夹更深刻。
它展示了在项目中投入了多少看不见的额外工作。

我使用 GitFlow,它在使用过程中需要更长的时间,但在完成的项目中更令人印象深刻,从而弥补了这一点。确保客户端看到 github 图形(或等效项)所有这些树枝看起来都很整洁,令人印象深刻。(除了实际上有用!

相关新闻:
问题跟踪系统。
在代码完成之前(当客户正在审查时)和之后,以允许他们添加新任务。
这不仅是一种划分任务和获得更多工作的方式,它让客户觉得这个项目仍然在我的脑海中。尽管我继续前进。
我使用 Collabtive,这绝对是可怕的,因为这些系统的发展,但看起来比我尝试过的任何其他东西都更令人印象深刻,看起来令人印象深刻的东西被认为是专业的。

评论

1赞 NikiC 10/28/2010
Git + Github = +10。对不起,我只能给 +1 :(
1赞 slebetman 10/30/2010
GitFlow 为 +1。对我来说,所有其他使用 git 的方式都是错误的。
4赞 3 revsIndustrial #25

企业集团应用

扪心自问 - 如果您正在运行在线商务系统,而您的卡支付供应商离线,您的客户是否仍然能够浏览您的产品,甚至使用不同的支付方式结账?

应用程序的构建方式应允许切换“开关”,这不会使整个站点进入“维护模式”,而只是以优雅的方式使应用程序中的页面或部分不可用,而应用程序的其余部分可供其他用户使用。

聚合应用程序可能是一个俗气的名字,但我完全确定它有更好的东西,但它绝对是许多人在开发可用应用程序时容易忘记的方法之一。

智能暴力破解保护

假设您的应用程序中有一个管理部件,其中包含相当多的客户信息。绝对是你不希望任何人拿到的数据。即使你有一个很好的盐和好的算法来散列你的密码,一个邪恶的用户仍然可以对你的登录表单进行DOS/彩虹表(蛮力?)攻击。

第一种选择显然是使用自动化软件来执行这些攻击,其次是通过对密码进行合格的猜测来手动执行。找到有关用户的足够信息来猜测他或她的密码真的很容易,考虑到仅使用 Google 就可以获得多少信息。 此外,如果您居住在瑞典这样的国家/地区 - 您只需给当局打一个电话就找不到有关一个人的信息 - 社会安全号码、伴侣姓名、婚姻状况、孩子姓名、宠物以及更多信息,这些信息都汇集在一起,作为普通用户对密码的非常合格的猜测。

如果我们看一下普通人如何选择密码,安全性应该非常容易受到损害。当然,我们可以对用户密码的长度、特殊字符等设置限制,但这不会影响这种情况。仍然可以进行暴力攻击。

如果用户尝试登录,但第二次尝试从未知 IP 登录失败,则应显示验证码以防止自动登录。在另一 (n) 次尝试失败后,该帐户应完全锁定,需要重新激活才能登录。

为了防止自动攻击侵蚀性能,一个好主意可能是完全阻止在设定的时间跨度内进行 (n) 次登录尝试失败的 IP,使其无法访问登录页面,直到再次被手动列入白名单。

0赞 SW4 #26

混淆(扩展评论)

这是为了扩展我之前发表的评论,该评论吸引了许多希望了解更多信息的用户的评论。因此,我将其从之前的答案中分离出来。

大量的 Web 应用程序都是基于 Javascript(以 Javascript 为中心)的,因此逆向工程的能力是巨大的,因为客户端可以访问代码中真正重要的部分,这些部分通常处理 UI 并指导后端完成其大部分任务。在某些时候,脚本可能会处理或触发包含应用程序处理的大部分数据的流量,因此很容易暴露更广泛应用程序的许多底层结构。保护你自己的IP的一个经常被忽视的技术是混淆代码,隐藏你编写的变量、函数和对象的真正目的。

混淆是一种用于 使代码复杂化。混淆使 代码何时更难理解 已反编译,但通常没有 对 法典。可以使用混淆程序 为了保护 Java 程序,请使 它们更难进行逆向工程。

混淆:http://en.wikipedia.org/wiki/Obfuscated_code

使用 PHP 对 Javascript (JS) 进行混淆相对容易,您可以简单地创建一个要替换的术语索引,使用 PHP 打开脚本,将这些术语替换为经过混淆的对应项并编写结果。

在 PHP 中动态混淆代码也很容易,尽管它会产生一些延迟(取决于文件/索引的大小)。动态混淆 JS 意味着值在访问/页面浏览量之间发生变化,从而增加了额外的噪音层,因为底层代码似乎在每次加载页面时都会发生变化。

为了说明如何将混淆引入他们的应用程序,我将研究一种可能的实现,它利用了一个很棒的 PHP 脚本 PHP Minify,它提供了更多的好处,将进行解释。

假设我们有 3 个 Javascript 文件,JS1、JS2 和 JS3。这些脚本必须按 1、2、3 的顺序出现,目前在主 HTML(或 PHP)文件的标头中单独链接,该文件将我们的应用程序交付给用户。JS1 和 JS2 是现成的外部框架,例如 jQuery 和 Prototype(忽略一个事实,你的应用程序中可能不会同时拥有这两个框架)。JS3 是你的 javascript,您可以使用自己的函数、变量、对象、类等来利用 JS1 和 JS2 中的功能。这是您的知识产权 (IP) 和/或出于法律、财务或自私 (!) 原因必须混淆。

显然,混淆我们的 JS 对我们来说是没有帮助的,然后必须进一步开发它。我们称函数为“function_to_save_secret_info”是有原因的,它使我们在编写代码时更容易(尽管这突出了为什么人们可能想要混淆)。因此,理想的情况是保留我们开发的 JS 文件,使用常识性命名,然后每次用户请求主 HTML/PHP 页面时,都会动态创建并提供其混淆版本。但是我们该怎么做呢?

最好的方法之一是使用 PHP Minify (http://code.google.com/p/minify/)。PHP Minify 具有许多优点。其中之一是能够将脚本分组并作为单个捆绑包提供。因此,我们不是在头文件中链接到 JS1、JS2 和 JS3,而是使用 PHP Minify 来设置一个由这三个组成的组,我们在头文件中链接到这个组,因此只有一个引用。这样做的优点包括:

  1. 更少的 HTTP 请求、更快的加载速度和更好的缓存(一个而不是三个)
  2. PHP Minify 自动 YUI 压缩组内的脚本,使加载时间更快(也是一种混淆方式)
  3. 更轻松地管理我们的 JS,更改组轻而易举
  4. 检查我们的代码不那么简单。

一旦我们这样做了,我们的母版页就会链接到我们的PHP缩小组,这很好 - 但我们实际上仍然提供相同的内容(所有这些都以更好的方式提供)。

但是,我们现在能做的是为 JS3 构建混淆例程。在 groupsConfig.php 脚本中,我们在 PHP 缩小中定义脚本组,我们更改组,将 JS3.js 替换为 JS3.obfuscated.js。但是,我们仍然有JS3.js的简单英文版本,JS3.obfuscated.js不存在。

所以基本上我们的主/主 HTML/PHP 页面在其标题中链接到我们的 JS 组,这是对 PHP Minify 的引用,其中该组定义为:

JS1.js
JS2.js
JS3.obfuscated.js

我们现在需要做的是构建一个关键表/函数来混淆 JS3 并输出 JS3.obfuscated.js。在最简单的层面上,我们所做的是编写包含以下内容的 PHP(例如,这不是最好的代码):

$terms_to_obfuscate=array(
   'my_secret_function',
   'my_secret_object',
   'my_secret_variable'
)

foreach ($terms_to_obfuscate as $key => $value) {
   //replace base64_encode(md5(rand(0,999))) with whatever you want to produce an obfuscated term
   $obfuscated_terms[]=base64_encode(md5(rand(0,999)));
}

$source_js=file_get_contents('JS3.js');
$fh = fopen('JS3.obfuscated.js', 'w+') or die("can't open file");
$obfuscated_js = str_replace($terms_to_obfuscate, $obfuscated_terms, $source_js);
fwrite($fh, $obfuscated_js);
fclose($fh);

这个脚本将要做的是打开我们的英语版本的 JS3,查找我们想要混淆的术语并用随机内容替换,将输出写入 JS3.obfuscated.js。如果我们将这段代码放在 PHP Minify 中的组定义之上,它将在每次调用 JS 组时运行......因此,每次加载我们应用程序的底层主 HTML/PHP 页面时,我们的脚本都会被随机混淆。请注意,这可能不是所有情况下的最佳实现,这只是说明性的。

这只是实现混淆的一种可能方法,但我们现在拥有的是压缩的 JS,可以更快地提供给我们的用户,随机混淆,我们仍然可以用“简单的英语”开发我们的脚本。我们所要做的就是更新我们的术语列表以混淆。有更好的方法可以做到这一点,这只是为了说明而不是确定概念背后的一般思想。

需要注意的是,混淆可能只适用于某些项目(无论如何它都不是特别开源),并不是对逆向工程的全面保护,但对于那些不太坚定的人来说,应该被视为更多的绊脚石。

评论

0赞 Industrial 10/28/2010
嗨,尔格。感谢您对混淆的解释!
0赞 SW4 10/28/2010
没问题 - 如果我可以提供更多细节或解释其他想法/概念/方法,请告诉我 - 尽管这可能不是最好的论坛!
9赞 NikiC 10/28/2010
-1.我不认为混淆真的增加了另一层安全性。如果你真的想知道代码是做什么的,你会花时间对它进行逆向工程。此外,我不同意将jQuery,Mootools和您的脚本捆绑到一个文件中是好的。jQuery 和 Mootools 都应该由 Google 提供,因为这样您就有最高机会将它们包含在缓存中。
0赞 Aaron Hathaway 10/28/2010
这太棒了!谢谢尔格!当然,它增加了另一层安全性,如果其他人确实想对其进行逆向工程,这是他们必须采取的额外步骤。
1赞 SW4 10/29/2010
@nikic,在答案中使用jQuery等 - 请注意,它被特别引用为仅用于说明目的!无论它们位于何处,您仍然应该从单个来源引用它们,以减少 http 缓存标头(YU 速度指南),对 scrip 进行分组并将它们作为任何来源的单个引用(YUI 和 W3C 指南)- 使用!YSlow。关于安全性,我认为任何使应用程序更难逆向工程的东西都会增加安全性——没有安全是纯粹的,每一项安全措施都只是绊脚石......任何事情都可以克服,但有些总比没有要好。
0赞 usr-local-ΕΨΗΕΛΩΝ #27

人类无法读取非常安全的会话 cookie

我相信人类可读的 cookie,当它们提到会话内容(即自动登录)时是一种安全威胁。根据PHP-Nuke的经验,它充满了(几年前,大约第7版)管理员登录漏洞,我开始加密cookie。 此外,由于 cookie 几乎都是明文传输的,因此我将它们绑定到 IP,或者更好的是子网。

I18n、l10n

本地化很重要。我从不在页面中编写人类可读的文本,我更喜欢使用共享字符串库用英语和意大利语制作网站。通常,我会用英语单词覆盖那些尚未翻译的字符串,以避免显示错误的字符串 ID

主题支持

如果用户可以在浏览过程中更改主题,那么 Web 应用程序在我看来看起来非常专业。主题不仅意味着 CSS,而且所有图形(图标、按钮)都必须在不触及核心的情况下进行更改。当我编写 phpMyBitTorrent 1.2 版本时,我非常关注主题,不幸的是,这导致相同的确切布局被不同的颜色/字体/图像公开。下一代主题是模板化的,因此您可以完全改变网站的外观。我相信当你使用MVC模式时,对你的网站进行模板化会更容易

跨数据库支持

或者,更好的是,数据库依赖性。我不喜欢在我的代码中显式调用 mysql_query()。我更喜欢在抽象层上运行查询,这样我就可以更改 DBMS(即更改为 SQLite 或 Oracle),而无需重写核心组件的代码。

伐木

日志记录是简化调试和收集 FFDA(现场故障数据分析)有用信息的最佳方式。Apache log4php 可以解决问题,但您必须使用足够的日志记录语句正确检测代码以获取可用信息。许多学术研究表明,开发人员从未达到足够的日志记录级别:他们记录过多或不够,并且由于缺少或不清楚的日志记录语句,错误通常仍然不清楚。不幸的是,日志会随着时间的推移而增加,因此您必须能够仅保留那些可以帮助您查找有关应用程序问题的记录。日志也可用于性能目的,但永远不要忘记日志记录引入的开销。最后,我目前的高年级论文是关于一套经过科学验证的日志记录规则,这些规则适用于复杂应用程序中的 FFDA,每个开发人员都应该看看。

ORM的

好吧,最后一点更多的是关于跨数据库支持。说实话,当我放弃PHP ASP.NET 时,我开始使用NHibernate ORM。如果我必须恢复 PHP,我会首先找到一个合适的 ORM 来避免代码中的查询。

这些是我的聪明主意

评论

0赞 mario 10/30/2010
+1 用于日志记录部分。你应该详细说明这一点,这似乎是最有趣的问题,你是专家等等。其他功能有点太常见了,第 1 点似乎是对原始主题(会话与隐私)的反驳。
0赞 usr-local-ΕΨΗΕΛΩΝ 10/30/2010
在这些评论中,甚至在答案中,记录部分肯定很复杂。太复杂了,我们想谈谈ffda......但是,如果有人感兴趣,我们可能会在SO聊天室见面并讨论它,所以我可以向大家介绍我当前的开源项目,该项目可以集成到PHP应用程序中。下个月我将完成我的论文,我想我会在 Sourceforge 上发布它(大量基准测试、测试用例和研究工作)以及代码和文档。
0赞 Hanseh #28

可读代码:

源代码必须写得很好,并且易于其他开发人员理解。它们必须具有短函数和离散类。它们必须具有描述性的函数和类名,这将导致较少的注释。函数或类必须具有单一的职责。每个函数的参数数量有限。智能编写的代码需要更少的分解、轻松升级、可扩展性等。

3赞 2 revsssokolow #29

全站SSL/TLS加密

正如最近发布的 Firesheep 所显示的那样,在开放的 WiFi 环境(例如许多图书馆、酒店和其他场所提供)以及任何仍在运行的未交换以太网段中窃取会话 cookie 是微不足道的。(理论上,在切换的上也是如此)

现在,Firesheep 甚至对普通 Joe 来说也只需单击两次即可操作,因此全站加密不再被视为奢侈品。(以及在会话 cookie 上设置安全标志,以确保兼容的浏览器不会意外地将它们泄漏到不安全的请求中)扩展和问题都不会消失。

根据 Adam Langly 的博客,Google 发现 SSL/TLS 并不像人们想象的那么糟糕,并且通过一些调整(他们在 Chrome 中构建),甚至可以有效地消除设置额外往返连接的延迟部分。

甚至证书成本也不像许多人想象的那么大,因为StartCom提供免费的SSL证书,并且其根证书已经存在于所有主要浏览器中。

评论

0赞 Nev Stokes 10/29/2010
我同意,但SSL并非没有自己的问题,例如空字符欺骗。
0赞 ssokolow 10/30/2010
真。。。以及强制证书等问题。这始终是一种权衡。
9赞 3 revsSteven de Salas #30

一个经常被忽视的:可打印的CSS。编写起来很痛苦,但对于想要在应用程序中打印出某些数据的用户来说,这有很大的不同。

<link href="print.css" rel="stylesheet" type="text/css" media="print"> 

评论

1赞 TerryE 2/27/2012
或者只是记住在你的CSS中包含一个(并在必要时)部分。这少了一个供浏览器加载的 CSS。@media print {}@media screen {}
3赞 Alex #31

国际化/语言环境支持

提供不同语言的应用程序翻译,并根据用户的区域设置提供适当的语言。

手机版

检测用户代理字符串,并提供适合移动/触摸的应用版本。使用 xhtml 移动配置文件很容易做到这一点。

使用支持多个后端的 ORM

无论是作为开发人员还是用户,能够通过编辑配置文件来交换数据库后端都很好。这样一来,你就可以在 SQLite 之类的东西上运行,供开发/单用户使用,也可以在 PostgreSQL 或 MySQL 等东西上运行,用于生产。

(不显眼)禁用 Javascript 时的通知

曾经在关闭或禁用 JS 的情况下去过 Stack Overflow 吗?有时我忘记了noscript已打开,SO很有帮助地告诉我。然后我可以决定是否要重新打开它;但至少我知道我缺少功能,而不仅仅是认为该应用程序很蹩脚。

Firebug/Javascript 日志记录

提供大量日志记录有助于调试 ajax 问题。只需在 JavaScript 中执行 console.log(message) 就会将消息记录到 Firebug。在应用程序配置文件中有一个生产/开发开关来打开或关闭它(让 php 不要在生产模式下生成日志消息)

0赞 Hooch #32

使用线程在后台尽可能多地工作。这样用户界面就永远不会冻结。 当过程记录器花费超过一秒钟才能完成时,会显示不错的进度条。

1赞 2 revs, 2 users 95%user401231 #33

自动固定链接

使用此功能,任何人都可以将其设置为链接的 href,它会自动获取页面的 url,以便于永久链接。

//Gets the URL of the current page
//set $p to yes to echo the urlturn the url or no to re
function page_url($p)
{
    $s = empty($_SERVER["HTTPS"]) ? ''
        : ($_SERVER["HTTPS"] == "on") ? "s"
        : "";
    $protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
    $port = ($_SERVER["SERVER_PORT"] == "80") ? ""
        : (":".$_SERVER["SERVER_PORT"]);
    switch ($p)
        {
        case 'yes':
            echo ($protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI']);
            break;
        case 'no':
            return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI'];
            break;
        default:
            echo('javascript:alert(\'invalid Argument in function page_url($p)\')');
        }
}
function strleft($s1, $s2)
{
    return substr($s1, 0, strpos($s1, $s2));
}