2017-08-01 117 views
1

问题很简单。一些JSon数据与服务器交换。 由于通信是相当复杂的,我需要日志,复杂的信息成为可能,看是否:使用jsoncpp时从JSon中去除私人数据的最佳方法

  • 服务器发送这是由代码
  • JSON有错字已于
  • 发送
  • ANS所以省略了新的价值

但是与此同时,任何私人数据都应该被虚拟数据所遮蔽。

所以不是看到日志:

{ 
    "secuityToken" : "asdasdgas234fsdfsaD", 
    "message" : "user private message" 
} 

这样的事情应该可以看出:

{ 
    "secuityToken" : "********", 
    "message" : "*******" 
} 

我的代码是C++所以jsoncpp正在使用中。我可以看到 最佳arproach是:

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应该是什么样子,是最通用的?

+0

而不是'container_t listOfKeysWithPrivateData'对于'std :: function isKeyPrivate'(或该模板参数) – Caleth

+0

这是技术细节。列表/向量或谓词选择是一个简单的次要目标。 –

回答

3

对我而言,这里直接的方法就够了。请致电ShadowPrivateData递归地为jsonValue的所有成员。在每个递归步骤中,您应该确定jsonValue是数组,对象还是都不是,并且正确地遍历它。为此,使用isArrayisObject

在迭代对象或数组的字段时,如果该字段不是聚合(对象或数组),请在listOfKeysWithPrivateData中搜索它的名称。如果在列表中发现字段的名称,确定字段的类型(使用isStringisDoubleisIntegral等),并与更换合适的领域:带*号用零替换字符串,数字等

声明listOfKeysWithPrivateDatastd::set<std::string>或类似的东西来执行对数搜索,而不是线性。

如何遍历聚合对象?对象使用getMemberNames,阵列使用size。换句话说,jsoncpp为json对象内省提供了一个完整的方法集合。

如果执行得当,这种方法应该审查所有敏感数据,而不要考虑它的复杂性。

0

所以我决定用@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)和它的魅力。

相关问题