防御式编程

11
在编写代码时,您是否有意识地进行防御性编程,以确保高质量的程序和避免您的代码被恶意利用,例如通过缓冲区溢出攻击或代码注入?您总是会为您的代码应用最低程度的质量标准吗?
14个回答

12

在我的工作领域,我们的代码必须是优质的。
所以,我们专注于两件主要的事情:

  1. 测试
  2. 代码审查

这些才能带来真正的收益。


4
类似于abyx,在我的团队中,开发人员总是使用单元测试和代码审查。除此之外,我还致力于确保不会加入可能被人们使用的代码 - 我倾向于仅编写基本方法集,以使对象按照规格要求正常运行。我发现,加入可能永远不会使用但提供功能的方法可能会无意中引入“后门”或系统中未预期/未预料的使用。
稍后再引入被要求的方法、属性和属性要容易得多,而不是预测可能永远不会出现的情况。

2
你所描述的也被称为YAGNI - http://en.wikipedia.org/wiki/YAGNI - abyx

1

我建议人们在开发环境中编写专制的代码,在生产环境中编写仁慈的代码。

在开发过程中,您希望尽早捕捉到不良数据/逻辑/代码,以防止问题被忽略或导致更晚出现的问题,其中根本原因很难追踪。

在生产中,尽可能优雅地处理问题。如果某些情况确实是无法恢复的错误,则处理并向用户呈现该信息。

这里举个例子,我们的代码用于规范化向量。 如果在开发中提供错误数据,它将会报错;而在生产中则会返回安全值。

inline const Vector3 Normalize( Vector3arg vec )
{
    const float len = Length(vec);
    ASSERTMSG(len > 0.0f "Invalid Normalization");
    return len == 0.0f ? vec : vec / len;
}

我们使用类似的方法来“增加”对遗留代码的问题检测。宏很容易添加,其唯一的效果是在测试时显示调试消息框。这不是一个神奇的解决方案,但比“return FALSE;”好,因为没有人会检查它。 - paercebal

1

我建议在数据进入“组件”或框架时保持防御性。在“组件”或框架内部,人们应该认为数据是“正确”的。

这样想,调用者必须提供正确的参数,否则所有函数和方法都必须检查每个传入的参数。但是,如果只对调用者进行检查,则仅需要进行一次检查。因此,参数应该是“正确的”,因此可以通过传递到较低级别。

  1. 始终检查来自外部来源(用户等)的数据
  2. “组件”或框架应始终检查传入的调用。

如果存在错误并且在调用中使用了错误的值,真正正确的事情是什么?您只有一个指示程序正在处理错误的“数据”,并且有些人喜欢ASSERTS,而其他人则希望使用高级错误报告和可能的错误恢复。无论如何,发现数据是有缺陷的,在少数情况下,继续处理它是好的。(请注意,至少不会出现服务器死机的情况)

从卫星发送的图像可能是一种尝试进行高级错误恢复的情况...下载自互联网的图像以放置错误图标...


0
简单的回答是:这取决于情况。过多的防御性编程可能会导致严重的性能问题。

0

我总是努力防止注入攻击之类的事情。不过,当您在内部局域网站点上工作时,大多数安全功能都感觉像是在浪费精力。虽然我仍然会做它们,但可能没有做得那么好。


0

嗯,安全方面有一套特定的最佳实践。至少对于数据库应用程序,您需要注意防止 SQL 注入攻击。

其他诸如哈希密码、加密连接字符串等也是标准做法。

从这里开始,具体取决于实际应用程序。

幸运的是,如果您使用 .Net 等框架,许多安全保护措施都已内置。


0

我认为即使是针对内部应用程序,您也必须始终进行防御性编程,因为用户可能仅凭运气就会写出破坏您应用程序的东西。尽管您可能不必担心他们试图欺骗您赚取金钱,但仍然要始终进行防御性编程并假设应用程序将失败。


0

使用测试驱动开发肯定会有所帮助。您一次只编写一个组件,然后在编写代码之前枚举所有可能的输入情况(通过测试),以确保您已经涵盖了所有情况,并且没有编写任何没人使用但可能会出错的代码。

虽然我不做任何正式的事情,但通常会花一些时间查看每个类,并确保:

  1. 如果它们处于有效状态,则保持有效状态
  2. 没有办法将它们构造成无效状态
  3. 在异常情况下,它们将尽可能优雅地失败(通常是清理和抛出)

0

这要看情况。

如果我是为自己使用而编写代码,那么我会尽可能编写最好的代码,让编译器成为我的朋友,帮助我发现警告等问题,但我不会仅仅为了创建类型而自动创建。

如果代码很可能被使用,即使只是偶尔使用,我会增加检查的级别。

  • 尽量避免使用魔法数字
  • 更好的变量命名
  • 完全检查和定义数组/字符串长度
  • 通过编程契约进行断言
  • 检查空值
  • 异常处理(根据代码的上下文情况而定)
  • 基本的解释性注释
  • 可访问的使用文档(如果是 Perl 等语言)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接