使用 jsoncpp 时从 JSon 剥离私有数据的最佳方法
Best way to strip private data from JSon when using jsoncpp
问题很简单。一些JSon
数据与服务器交换。 由于通信非常复杂,我需要尽可能复杂的信息,以查看是否:
- 服务器发送代码省略的新值
- 带有错别字的JSon被发送
- 等等
但与此同时,任何私人数据都应该被虚拟数据所掩盖。
因此,请在日志中看到:
{
"secuityToken" : "asdasdgas234fsdfsaD",
"message" : "user private message"
}
应该看到这样的东西:
{
"secuityToken" : "********",
"message" : "*******"
}
我的代码C++,因此正在使用jsoncpp
。 我能看到的最好的理由是:
bool ProcessServerMessage(const std::string& message)
{
Json::Value jsonValue;
Json::Reader reader;
if (reader.parse(sMessage, jsonValue, false))
{
auto logValue = ShadowPrivateData(jsonValue, listOfKeysWithPrivateData);
LOG() << " JSOn recived: " << logValue;
…
}
质疑ShadowPrivateData
应该是什么样子,才能最通用?
对我来说,一个简单的方法就足够了。只需递归地调用ShadowPrivateData
即可jsonValue
的所有成员。在每个递归步骤中,您应该确定jsonValue
是数组、对象还是两者都不是数组、对象,并正确遍历它。为此使用isArray
和isObject
。
遍历对象或数组的字段时,如果字段不是聚合(对象或数组(,请在listOfKeysWithPrivateData
中搜索其名称。如果在列表中找到字段的名称,请确定字段的类型(使用isString
、isDouble
、isIntegral
等(并将字段替换为适当的值:将字符串替换为星号,将数字替换为零等。
将listOfKeysWithPrivateData
声明为std::set<std::string>
或类似的东西以执行对数搜索而不是线性搜索。
如何循环访问聚合对象?对对象使用getMemberNames
,对数组使用size
。换句话说,jsoncpp 为 json 对象自省提供了完整的方法集合。
如果实施得当,这种方法应该审查所有敏感数据,jsonValue
而忽略其复杂性。
所以我接受了@Sergey建议,并有这样的东西:
// in header
class CJSONUtils
{
public:
static Json::Value HidePrivateData(const Json::Value& value,
const std::vector<std::string>& pathSufixes);
private:
static void ShadowPrivateData(Json::Value& value,
const std::vector<std::string>& pathSufixes,
const std::string& sPath);
static bool IsPrivatePath(const std::string& sPath,
const std::vector<std::string>& pathSufixes);
static std::string MaskPrivateText(const std::string& sPrivateText);
};
// in cpp
#include "JSONUtils.h"
#include "StringUtils.h"
#include <algorithm>
#include <json/json.h>
using namespace std;
using namespace Json;
Value CJSONUtils::HidePrivateData(const Value& value,
const vector<string>& pathSufixes)
{
Value result { value };
ShadowPrivateData(result, pathSufixes, {});
return result;
}
void CJSONUtils::ShadowPrivateData(Value& value,
const vector<string>& pathSufixes,
const string& sPath)
{
switch (value.type())
{
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue:
if (IsPrivatePath(sPath, pathSufixes))
{
value = Value { MaskPrivateText(value.asString()) };
}
break;
case arrayValue:
for (auto& arrayValue : value)
{
ShadowPrivateData(arrayValue, pathSufixes, sPath + "[]");
}
break;
case objectValue:
for (auto it = value.begin(); it != value.end(); ++it)
{
ShadowPrivateData(*it, pathSufixes, sPath + "." + it.key().asString());
}
break;
}
}
bool CJSONUtils::IsPrivatePath(const string& sPath,
const vector<string>& pathSufixes)
{
return std::any_of(pathSufixes.begin(),
pathSufixes.end(),
[&](const string& sSufix)
{
return EndsWith(sPath, sSufix);
});
}
std::string CJSONUtils::MaskPrivateText(const std::string& sPrivateText)
{
if (sPrivateText.length() < 15)
{
return std::string(sPrivateText.length(), '*');
}
ostringstream result;
result << "< *" << sPrivateText.length() << " characters * >";
return result.str();
}
现在Json::Value
由于重载流运算符可以像这样使用:
LOG() << " JSON received: " << CJSONUtils::HidePrivateData(jsonRoot, listOfPrivateItemsPaths);
我已经为它编写了测试(gtest(,它就像魅力一样工作。
- 在c代码之间共享数据的最佳方式
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 将线程中的数据存储到全局容器的最佳方法?
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?
- 在 c++ 中解析数据包数据的最佳方法是什么?
- 使用 QT C++过滤大数据的最佳方式
- 在wxWidgets的事件中包含我自己的数据的最佳方法是什么?
- 用于筛子的最佳数据结构是什么(即一些被划掉的数字列表)?
- 用于存储分组关系和支持外观的最佳数据结构
- 适用于频繁更改的大型数据集的最佳数据结构
- 将数据从一个应用程序单向发送到另一个应用程序的最佳做法
- 点遍历的最佳数据结构
- 使用 jsoncpp 时从 JSon 剥离私有数据的最佳方法
- 代表软件包安装和系统依赖关系的最佳数据结构
- 在 c++ 中,在线程之间共享数据容器的最佳方法是什么?
- 组织从内存读取的数据的最佳方法(用于调试)c++
- 数字序列的最佳数据结构 [0:9]
- 什么是在C 中存储结果INT*的最佳数据类型
- 我的数据结构的最佳序列化方法
- 存储数据列表并自动分配给结构的最佳方法是什么