betway88必威[译] 防守式编程的办法。防御性代码的点子,对bug说再见。

  • 原稿地址:The Art of Defensive
    Programming

为何开发人员不修安全代码?

  • 初稿作者:Diego
    Mariani
  • 译文出自:掘金翻译计划
  • 译者:GiggleAll
  • 校对者:tanglie1993
    , fghpdf

咱俩当这边不再谈论“干净之代码”。
我们在讨论更多的事物,从纯的履角度看,软件的安全性及平安。是的,因为一个未安全之软件几乎没因此。

怎开发人员不修安全代码? 我们不再在此地讨论 “绝望之代码
。我们打一个纯粹的角度,软件之安全性来谈谈还多的东西。是的,因为一个勿安全之软件几乎是绝非因此之。让咱来探不安全之软件意味着什么。

给我们看不安全之软件带来的损失。

  • 欧洲航天局的 Ariane 5 Flight 501 在起飞后 40
    秒(1996年6月4日)被弄坏。10
    亿美元之
    原型火箭出于机载导航软件中之缪而自毁。

  • 在 20 世纪 80 年代,一个治疗机中决定 Therac-25
    辐射的之代码错误,导致该给用了量之 X 射线致使至少五称病人死亡。

  • MIM-104 爱国者的软件错误致其系统时钟在 100
    小时上内偏移三分之一秒,以至于无法稳定及截留来袭导弹。伊拉克导弹袭击了沙特阿拉伯以达哈兰之一个军旅大院(
    1991 年 2 月 25 日 ),杀害了 28 叫做美国口。

欧洲航天局之Ariane 5 Flight 501在起飞后40秒(1996年6月4日)被毁坏。
10亿美元之原型火箭由于机载指导软件中的一无是处而自毁。

这些事例可以让咱们认识及编辑安全的软件,特别是在某些情况下是何其重要。在其他以状态下,我们呢应当知道我们软件错误会带为咱什么。

支配Therac-25放射治疗机的代码中之缪直接招了于80年份,当该给予用过量之X射线时,至少要五曰患者身故。

防守式编程角度一

为何自己觉得防守式编程在好几品种被凡一个发现这些题目的好办法?

守卫不可能,因为不容许拿可能出。

对此防御性编程有成千上万概念,它还在于安全性的级别与您的软件项目所欲的资源级别。

防守式编程是一种防守式设计,旨在确保于意料之外的动静下软件的连绵功能,防守式编程实践时受用当高可用性,需要安全的地方

维基百科

自身个人认为这种方法可当您处理一个死之、长期的、有那么些人数参与的花色。
例如,需要大量掩护的开源项目。

为了实现防守式编程方法,让自己谈谈自己个人简陋的眼光。

MIM-104爱国者的软件错误造成其系统时钟在100小时之内漂移三分之一,导致力不从心稳定与阻止入射导弹。
伊拉克导弹袭击了沙特阿拉伯达哈兰一个军事大院(1991年2月25日),造成28名为美国人数死。

尚未相信用户输入

要你连会收下你意料之外的东西。这当是若当防守式程序员的方法,针对用户输入,或者平常上而的系统的各种东西。因为咱们好预料到意外的,尽量做到尽量严格。断言)你的输入值是你望的。

betway88必威 1

The best defense is a good offense

攻击就是不过好的看守

(将输入)列入白名单而非是将其放到黑名单中,例如,当证图像扩展名时,不检查无效的类,而是检查中的类,排除拥有其他的路。
在 PHP 中,也发成百上千之开源验证库来使您的干活双重易于。

进攻就是极其好之防御,控制而严格。

当时该可以理解安全软件多么重要,特别是在某些圈子被出多重要。
但在旁使用状况下,我们应有理解我们的软件错误将见面招致什么伤害。

以数据抽象

OWASP
十颇安全漏洞

中的首先单凡是流入。这表示有人(很多人口)还未曾下安全工具来查询他们之数据库。请用数据库抽象包和仓库。在
PHP 中君得行使
PDO
来保险基本的流入保护。

betway88必威 2

决不再过去轮子

公不要框架(或微框架)?
你不怕是欣赏无理由的做额外之做事。恭喜你!只要是由此精美测试、广被信赖的泰的代码,你就算足以尽管用于各种新特点(不仅是框架)的出,而休是光因它们是现已去好之轮的原由而更造轮子。你自己去轮子的唯一原因是您需要部分休在或者有但非相符您的求(性能不好好,缺少的效应等)。

充分(使用框架)我们遂它们呢智能代码用,它值得所有。

看守编程的率先征缴

毫无相信开发人员

防守式编程可以同名防御性驾驶的东西有关。在防守驾驶着,我们若我们周围的每个人还来或发错误。
所以我们须小心别人的表现。这些同适用于咱俩的防守式编程,作为开发者,我们不应当相信任何开发者。我们啊同无该相信我们的代码。

于过剩人参与的特别色蒙,我们得来多两样的不二法门来修和集体代码。
这也或导致乱,甚至又多之错。
这就是是怎么我们联合编码风格及运代码检测器会如我们的活着更是自在。

怎自己以为防御性编程在好几品种的种被钻这些问题的好办法?

写SOLID代码

马上是本着一个防守式程序员困难的地方,writing code that doesn’t
suck
。这是众多人数了解和讨论的作业,但不曾丁的确关心或投入对的注意力和努力来实现
SOLID代码

叫咱来拘禁有不好的例证。

永不:未初始化的性质

<?php

class BankAccount
{
    protected $currency = null;
    public function setCurrency($currency) { ... }
    public function payTo(Account $to,$amount)
    { 
        // sorry for this silly example
        $this->transaction->process($to,$amount,$this->currency);
    }
}

// I forgot to call $bankAccount->setCurrency('GBP');
$bankAccount->payTo($joe,100);

每当这种情景下,我们务必铭记,为了发出付款,我们要事先调用 setCurrency

这是一个颇坏的工作,像这样的状态更改操作(发出付款)不该在个别单步骤使用有限只(或多只)公共措施。
我们照例可以出无数道来会,但是咱不能不就来一个简练的公措施,以改状态(对象应该永远不见面处于不一致的状态)。

于这种情景下,我们得开得还好,将无初始化的特性封装到 Money
对象中。

<?php

class BankAccount
{
    public function payTo(Account$to,Money$money){ ... }
}

$bankAccount->payTo($joe,newMoney(100,newCurrency('GBP')));

设它们万无一失。 不用使用不初始化的靶子属性

Don’t: Leaking state outside class scope.

甭:类作用域之外的暴露状态。

<?php

class Message
{
    protected $content;
    public function setContent($content)
    {
        $this->content=$content;
    }
}

class Mailer
{
    protected $message;
    public function__construct(Message$message)
    {
        $this->message=$message;
    }
    public function sendMessage(
    {
        var_dump($this->message);
    }
}

$message = new Message();
$message->setContent("bob message");
$joeMailer = new Mailer($message);

$message->setContent("joe message");
$bobMailer = new Mailer($message);

$joeMailer->sendMessage();
$bobMailer->sendMessage();

以这种状态下,消息由此引用传递,结果以于有限种植情况下还是 “joe
message”
。 解决方案是在 Mailer 构造函数中克隆消息对象。
但是咱应当总是尝试利用一个(不可变的)值对象去替一个简易的
Message mutable对象。当你得的时刻用不可变对象

<?php

class Message
{
    protected $content;
    public function __construct($content)
    {
        $this->content = $content;
    }
}

class Mailer 
{
    protected $message;
    public function __construct(Message $message)
    {
        $this->message = $message;
    }
    public function sendMessage()
    {
        var_dump($this->message);
    }
}

$joeMailer = new Mailer(new Message("bob message"));
$bobMailer = new Mailer(new Message("joe message"));

$joeMailer->sendMessage();
$bobMailer->sendMessage();

守护不容许,因为不容许也会有。

写测试

咱还需要说把什么?
写单元测试将救助你遵守共同的标准,如大集,单一责任,低耦合和不易的对象成
它不仅仅帮您测试小单元,而且也能测试你的对象的布局的方。
事实上,你晤面掌握地察看,为了测试你的略微作用要测试多少只单元以及你需要效法多少个目标,以促成100%底代码覆盖率。

防御性编程有众多定义,它还取决于“安全性”级别及你的软件类所待的资源级别。

总结

盼望你喜欢就首文章。
记住这些只是是建议,何时、何地采纳这些建议,这取决你。

防御性编程是同栽防御性设计,旨在确保以不可预见的状态下软件的累效力。防御性规划做法常用于需要高可用性,安全性还是稳定的地方

自己个人觉得这种方式可当您处理一个大,使用周期长之大半人口踏足种。例如,对于欲大量护卫的开源项目。

受咱探讨有略的关键点,以促成防御性编程方法。

决不相信用户输入

只要你总是会收你不愿意的物。那么您的措施应该作为一个防御性程序,针对用户输入,或貌似进入而系统用户。这即是咱们可预期到意想不到的结果。尽量做到尽量严格。断言您的输入值是公想之。

最好的守卫是进攻

列入白名单而非是地下名单,例如,当证图像扩展名时,不反省无效的类型,但检查中的门类,排除有其他的项目。在PHP中,你呢产生那么些底开源验证库,使你的办事再次易。

最为好的防御是一个好之抢攻。要小心谨慎。

使抽象数据库

OWASP十死安全漏洞中之首先个凡是流入。这意味着有人(很多总人口于那边)还从未采取安全工具来查询他们的数据库。请以数据库抽象包以及货栈。在PHP中,您可以PDO来确保基本的流入保护。

不用还发明轮子

汝不以框架(或微框架)?你爱开额外的劳作,没有理由,恭喜您!它不光是框架,而且对于新的效益,你得生轻地使用,经过测试,受到许多的开发人员和安宁之相信,而无是一味为协调打的东西。你当自己创立一个事物的唯一原因是您需要部分非存在或者有但非相符你的待(性能不尽如人意,缺少的效能等)。

永不相信开发人员

防御性编程可以和防御性驾驶的东西有关。在看守驾驶负,我们而我们周围的每个人且有或发错误。所以我们得小心别人的行。同样的概念呢适用于防御性编程,开发人员不应相信外开发人员的代码。也未应有相信我们协调的代码。

当特别品类被,许多人口踏足,我们好起成百上千异的方式来修和团伙代码。这吗可能致乱,甚至更多的荒谬。所以我们应有规范编码风格。

写入SOLID代码

当时是一个(防御)程序员的困苦有,编写代码不抽烟。这是众多丁明白和座谈的工作,但并未丁真的关心或投入对的注意力和努力来实现SOLID代码。

深受咱们看有的良之事例

未初始化的属性

class BankAccount

{

protected $currency = null;

public function setCurrency($currency) { … }

public function payTo(Account $to, $amount)

{

// sorry for this silly example

$this->transaction->process($to, $amount, $this->currency);

}

}

// I forgot to call $bankAccount->setCurrency(‘GBP’);

$bankAccount->payTo($joe, 100);

于这种场面下,我们须铭记,为了闹付款,我们得调用第一个setCurrency。
这是一个异常坏的事体,像这么的状态更改操作(发出付款)不应当运用简单(n)个集体艺术以少单步骤。
我们还可以来诸多措施来付,但是我们要就发生一个略的共用艺术,以反状态(对象不该处于不相同的状态)。

每当这种状况下,我们做得又好,将不初始化的性能封装到Money对象中。

class BankAccount

{

public function payTo(Account $to, Money $money) { … }

}

$bankAccount->payTo($joe, new Money(100, new Currency(‘GBP’)));

绝不以非初始化的对象属性

色范围以外的透漏状态。

class Message

{

protected $content;

public function setContent($content)

{

$this->content = $content;

}

}

class Mailer

{

protected $message;

public function __construct(Message $message)

{

$this->message = $message;

}

public function sendMessage(

{

var_dump($this->message);

}

}

$message = new Message();

$message->setContent(“bob message”);

$joeMailer = new Mailer($message);

$message->setContent(“joe message”);

$bobMailer = new Mailer($message);

$joeMailer->sendMessage();

$bobMailer->sendMessage();

当这种状况下,消息经引用传递,结果将以点滴种植情景下还是“joe message”。
解决方案是于Mailer构造函数中克隆信对象。
但是咱们相应总是尝试采取一个(不可变的)值对象,而未是一个简便的Message
mutable对象。 尽可能使用不可变对象。

class Message

{

protected $content;

public function __construct($content)

{

$this->content = $content;

}

}

class Mailer

{

protected $message;

public function __construct(Message $message)

{

$this->message = $message;

}

public function sendMessage(

{

var_dump($this->message);

}

}

$message = new Message();

$message->setContent(“bob message”);

$joeMailer = new Mailer($message);

$message->setContent(“joe message”);

$bobMailer = new Mailer($message);

$joeMailer->sendMessage();

$bobMailer->sendMessage();

当这种情景下,消息经引用传递,结果以于有限种植情景下还是“joe message”。
解决方案是以Mailer构造函数中克隆音对象。
但是我们应该总是尝试利用一个(不可变的)值对象,而未是一个简短的Message
mutable对象。 尽可能使用不可变对象。

class Message

{

protected $content;

public function __construct($content)

{

$this->content = $content;

}

}

class Mailer

{

protected $message;

public function __construct(Message $message)

{

$this->message = $message;

}

public function sendMessage()

{

var_dump($this->message);

}

}

$joeMailer = new Mailer(new Message(“bob message”));

$bobMailer = new Mailer(new Message(“joe message”));

$joeMailer->sendMessage();

$bobMailer->sendMessage();

尚亟需说些什么?
写单元测试将援助而坚持广泛的格,如大凝聚力,单一责任,低耦合和科学的目标成。
它拉而测试工作的微单位案例,你的目标的构造的主意。
事实上,你会了解地观望,当测试小作用时要测试多少只案例和需要效法多少个目标,以贯彻100%底代码覆盖率。

betway88必威 3

意在您喜爱就首文章。
记住这些仅是建议,下次你就是亮啊时候,在何用他们。

转载请晓。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注