跳转至

IWebCore的安全策略

在c++当中,安全问题是一个重大的问题。c++的逻辑是相信用户,让用户对自己的行为负责。比如包括但不限于以下经常出现的问题:

  • 内存管理容易翻车:比如用了野指针(指向已释放的内存)或者数组越界,轻则程序崩溃,重则被黑客利用(比如盗取数据)。
  • 类型转换太随意:比如把负数赋值给无符号数,或者大数塞进小容器,结果数字“溢出”导致计算错误。
  • 没有安全防护网:比如访问空指针时,不像 Java 会报空指针异常,C++ 直接崩溃。

c++ 标准委员会也有一系列的安全提案,Bjarne 也在公开场合一再呼吁c++安全的方案和策略。

“安全问题不是修修补补就能解决的,必须从设计层面考虑。我们要像造汽车一样,既要跑得快,也要有安全带和安全气囊。”

所以在 IWebCore 中,结合c++的通用做法,提出自己的安全策略

编译期安全

用户应该编写严格的代码,对于一些问题,应该在编译器就能被拦截下来。对于IWebCore而言,IWebCore提供更严格的静态期检测,防止不合法,不合格的代码被编译出来。

  • static_assert 断言 / if constexpr 静态判断

通过静态断言和编译期判断,在编译器阻止非法的代码编译

  • 函数签名中const 的大量使用

用户通过函数签名来限制代码的编译

  • 模板规则的使用

通过 sfinea机制来选择合法的代码,阻止不合法不合逻辑的代码。

运行初期 Fast-Fail

IWebCore的开发过程中,用户的代码时被任务化,模块化的。开发者所编写的代码是整个代码中的一个个功能点,这些功能点会被封装成一个个的任务(Task),在项目运行的初期,初始化这一系列的任务。在所有的任务完成初始化的时候,程序开始提供服务。

所以对于IWebCore而言,用户可以在任务执行的时候对代码的逻辑功能和内容等进行先期的判断,如果代码符合一定的逻辑,则可以继续执行,如果不符合逻辑,则直接让任务失败,提前暴露问题,让问题在开发阶段就被发现和解决。

关于Fast-Fail 请参考 Abort-FastFail文档。

IWebCore 执行运行初期 Fast-Fail 功能的是我们的 Abort 机制。具体内容请参考该文档。

运行期安全

使用 IResult

IResult 是对 std::optional 的一个重命名,让该机制可以自然,无缝的和 IWebCore 的命名机制结合起来,用户使用的时候不显突兀。

在用户对于一个函数的调用的时候,函数受到输入内容和环境的影响,不一定能够正确返回用户想要的数据。一般的处理方式有四种,

  • 传入一个额外的变量。标记是否是成功的,
  • 约定返回值的个一个特定值是错误的值,比如 数字0 是错误的,其他的值是正常值。
  • 返回一个复合对象,复合对象中有标记成功与否的值,比如标准库中的std::optional, std::expected
  • 抛出异常,让用户自行处理。

其中第一种方法是运行最快速的,第三种方法是最便捷的。IResult 使用的是第三种方法。在 IWebCore中,我们大量使用 IResult 进行函数返回值的处理,比如对于数值的转换,对于 配置信息的请求等等。

具体的内容可以参考文档 IResult

异常(Exception)

c++ 异常在我看来绝对是一个能避免就避免的东西,我在意的不是他的运行速度(运行出问题了,花时间解决我是认的),而是他的的确确不好用,相对于 java 异常而言,就像一个小孩子,而java异常则是一个四平八稳,行事周到,但却臃肿的老人。

不好用归不好用,但却没有不用他的意思,对于以下的两种场景,还是要用的,但是用的时候需要注意他的小脾气。这两种场景都是 额外变量或者 IResult 不好使的地方。

  • 跨多层函数调用的错误

这个比如在做html嵌套回调生成的时候,你不知到哪里出现错误,但你可以在任意路径抛出异常,只需要在顶层进行拦截就可以。

  • 对于环境变化导致的不可控异常,

比如数据库链接的变化,这个是网络,服务器等等一系列不知道哪里的问题,平时不用关心,但是出问题要解决的。我的做法是直接抛异常,在最顶层进行拦截处理。

此外,还有一些异常,需要用户自己判断,比如 零除异常,空指针异常等错误型异常,这些在java 中只会崩溃线程却在c++中崩溃程序的异常,需要用户自己提前判断,预防性编程,手动处理。

IWebCore中的异常可以参考 IException

安全编码实践

RAII

在IWebCore中,尽量避免通过 new 初始化一个对象,通过delete 删除一个对象,除非迫不得已。IWebCore的实践中,也很少用 new 生成对象,而是通过严谨有序的代码结构,来完成一个个的对象初始化。

另外,对于 static const 静态局部常量是非常欢迎的。

尽量使用IWebCore提供的基类

IWebCore中提供的大量的基类,用户可以继承这些基类,重载他的函数来完成自己的功能。

其他的内容有大量的书籍可以参阅。