【问题标题】:Protobuf C++ required fields are not checked/enforced未检查/强制执行 Protobuf C++ 必填字段
【发布时间】:2017-05-17 06:44:40
【问题描述】:

我是 Protocol Buffers 的新手,目前我看到以下问题:

我们将proto2 语法与Protocol Buffers 3.2.0 库一起使用,并观察到required 字段在序列化期间未强制执行。

这里有一个 Catch C++ 测试的基本示例:

syntax = "proto2";

package simple_test;

message SimpleMessage
{
  required string field1 = 1;
  required string field2 = 2;
}

#include "simple.pb.h"
#include <catch.hpp>
#include <string>

SCENARIO("Verify that serialization with missing required fields fails", "[protobuf]")
{
  GIVEN("a message")
  {
    simple_test::SimpleMessage m;

    WHEN("field1 is set and field2 is not and both are required")
    {
      m.set_field1("aaa");

      THEN("serializing this message to string buffer must fail")
      {
        std::string buffer;
        CHECK_FALSE(m.SerializeToString(&buffer));
        REQUIRE(buffer.empty());
      }
    }
  }
}

m.SerializeToString(&amp;buffer) 返回true 并且buffer.empty()false

我知道的

required 字段已在 Protobuf v3 中删除。

我的问题

  • 我是否可以使用 Protobuf v3 强制执行这些检查的设置或任何类型的配置开关?
  • 用例会发生什么:

    proto2 使用 Protobuf v3 编译器编译的消息。此消息以部分填写的必填字段结束,并将发送到强制执行 required 字段的 Protobuf v2 端点。这是否实际上意味着只发送了字节,因为消息无效并且将被拒绝?

  • 我应该从 v3.2.0 降级到 2.x 以禁止在客户端发送不完整的消息吗?

【问题讨论】:

    标签: c++ protocol-buffers


    【解决方案1】:

    我带来了这份我之前监督过的文档:

    Standard Message Methods 并且有以下文档:

    标准消息方法

    每个消息类还包含许多其他方法,可让您检查或操作整个消息,包括:

    bool IsInitialized() const;:检查是否所有必填字段都已设置。

    这就是我需要的! Protobuf 再次很棒!

    【讨论】:

      【解决方案2】:

      我是否可以使用 Protobuf v3 强制执行这些检查的设置或任何类型的配置开关?

      您是否尝试过在调试配置中构建 protobuf?我想你会发现它会在这种情况下断言。

      用例会发生什么:

      proto2 使用 Protobuf v3 编译器编译的消息。此消息以部分填写的必填字段结束,并将发送到强制执行必填字段的 Protobuf v2 enpoint。这是否实际上意味着只发送了字节,因为消息无效并且将被拒绝?

      在这种情况下,接收者可以ParsePartialFromXXX 接收发送的内容。他可以用message.has_xxx()测试消息的有效性

      我应该从 v3.2.0 降级到 2.x 以禁止在客户端发送不完整的消息吗?

      我不会。也许为每种消息类型编写一个检查器来断言每个必填字段都存在。更好的是,以 proto3 方式考虑它,并将缺失的字段视为接收器中的默认值。 protobuf 文档建议永远不要将 required 字段添加到现有消息类型,并建议在创建字段 required 之前“仔细考虑”。您可以将其理解为“糟糕,必填字段的概念是错误的”。

      【讨论】:

      • 感谢您的回复,即使它对 Protobuf 变异的方式令我失望。调试模式不是一个选项,即使我发现它断言比什么?关于其他两个问题,我阅读了必填字段,在我们的案例中,我不想拥有任何灵活的协议。这应该是“我的方式或高速公路”。我还读到,即使在谷歌,也有两个阵营在支持required 并反对它。
      • @ovanes 我知道这对我们 c++ 人来说很失望——我们已经习惯了强类型。但是当然protobuf最终只是一个序列化协议。服务器/接收者必须是正确与否的最终仲裁者。恶意客户端可以发送任何内容。因此,在我们的 protobuf rpc 实现中,服务器会检查所有不变量,如果消息格式错误或不完整,则返回异常通知。
      • 是的,但这也违反了 DRY。有多少人使用 Protobuf 并且所有人都必须实施这种required 检查。我了解是否有人需要检查更复杂的不变量,例如该字段的值 X 是否比另一个应该具有 Y。但是如果有 required 这样的东西它也应该工作:(而不是问:是的!只是膨胀您的代码包含大量 if 语句并进行检查。AFAIK Protobuf 甚至不支持访问者模式,在没有 ifs 的情况下进行这种调度和验证。
      • @ovanes 您可以遍历消息描述符的字段描述符并检查是否需要,因此您可以使用一个引用基类Message的函数检查所有消息@
      猜你喜欢
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2020-03-29
      • 1970-01-01
      相关资源
      最近更新 更多