Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB序列化C#-添加其他加密字段属性_C#_Mongodb_Mongodb .net Driver - Fatal编程技术网

MongoDB序列化C#-添加其他加密字段属性

MongoDB序列化C#-添加其他加密字段属性,c#,mongodb,mongodb-.net-driver,C#,Mongodb,Mongodb .net Driver,我正在尝试用c语言编写MongoDb序列化程序,它允许我通过[Encrypt()]属性来修饰属性,然后在运行时,它允许我生成一个名为PropertyName\u Encrypted的附加属性,该属性将包含加密值 反序列化时,将在父属性中设置加密的属性值,以便该属性的默认GET始终返回加密的值。然后,用户将对该对象调用可选的Decrypt()方法以获取解密值 在这样做的过程中,我遇到了一些有趣的挑战: 序列化当前元素时,如何向文档添加其他属性?如何获取当前元素的名称 有没有办法从文档/对象中读取特

我正在尝试用c语言编写MongoDb序列化程序,它允许我通过[Encrypt()]属性来修饰属性,然后在运行时,它允许我生成一个名为PropertyName\u Encrypted的附加属性,该属性将包含加密值

反序列化时,将在父属性中设置加密的属性值,以便该属性的默认GET始终返回加密的值。然后,用户将对该对象调用可选的Decrypt()方法以获取解密值

在这样做的过程中,我遇到了一些有趣的挑战:

  • 序列化当前元素时,如何向文档添加其他属性?如何获取当前元素的名称

  • 有没有办法从文档/对象中读取特定属性?例如,假设我想传递一个对称加密密钥并读取该密钥,以便在序列化当前元素时加密数据?我有办法做到吗

  • 以下是我迄今为止所做的事情:

  • 我构建了一个Encrypt属性,如下所示:

    [AttributeUsage(AttributeTargets.Property)]
     public class EncryptAttribute : Attribute
    {
    private readonly EncryptedFieldType _fieldType;
    private readonly bool _tokenizeDisplay;
    private readonly string _encryptedFieldName;
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="fieldType">The field type to encrypt. Useful if display needs to show some formatting. If no formatting is necessary, simply set to "Other".</param>
    /// <param name="tokenizeDisplay">If set to true, will persist the tokenized value in the original field for display purposes.</param>
    /// <param name="encryptedFieldName">Optional. If set, will save the encrypted value in the field name specified. By default all encrypted field values are stored in the corresponding _Encrypted field name. So EmailAddress field if encrypted, would have value under EmailAddress_Encrypted.</param>
    public EncryptAttribute(EncryptedFieldType fieldType, bool tokenizeDisplay, string encryptedFieldName = "")
    {
        _fieldType = fieldType;
        _tokenizeDisplay = tokenizeDisplay;
        _encryptedFieldName = encryptedFieldName;
    }
    }
    
  • 映射程序只需检查文档中哪些属性具有要添加序列化程序的Encrypt属性:

    public sealed class Mapper
    {
        public void Map(Assembly assembly)
        {
        var encryptableTypes = assembly.GetTypes().Where(p =>
            typeof(IEncryptable).IsAssignableFrom(p) && p.IsClass && !p.IsInterface && !p.IsValueType &&
            !p.IsAbstract).ToList();
    
        if (encryptableTypes.Any())
        {
            foreach (var encryptableType in encryptableTypes)
            {
                Map(encryptableType);
            }
        }
    
    }
    
    private void Map(Type documentType)
    {
        var properties =
            documentType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        if (properties.Length <= 0)
        {
            return;
        }
    
        foreach (var property in properties)
        {
            RegisterEncrpytionSerializer(property, typeof(EncryptAttribute), documentType);
        }
    }
    
    private void RegisterEncrpytionSerializer(PropertyInfo property, Type encryptAttributeType, Type documentType)
    {
        var encryptAttributes = property.GetCustomAttributes(encryptAttributeType, false).ToList();
        if (!encryptAttributes.Any()) return;
    
        var memberMap = BsonClassMap.LookupClassMap(documentType).GetMemberMap(property.Name);
        memberMap?.SetSerializer(new EncryptionSerializer());
    }
    
    公共密封类映射器
    {
    公共空间地图(部件)
    {
    var encryptableTypes=assembly.GetTypes()。其中(p=>
    typeof(IEncryptable).IsAssignableFrom(p)&&p.IsClass&&p.IsInterface&&p.IsValueType&&
    !p.IsAbstract).ToList();
    if(encryptableTypes.Any())
    {
    foreach(encryptableTypes中的变量encryptableType)
    {
    Map(encryptableType);
    }
    }
    }
    专用空心贴图(类型documentType)
    {
    var特性=
    GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
    如果(properties.Length您是否使用服务来保存/检索实际调用数据库的项目

    我认为您应该将写入/读取加密值的责任转移到调用服务(即存储库实现)而不是BsonSerializer

    对我来说,加密/解密是持久层的一部分,是应用程序在需要时无法处理的,这是有道理的

    您的实现只针对要序列化的指定属性。创建另一个属性没有意义

    第二个想法是,您建议的基于
    Decrypt()
    更改值的属性方法可能不是一个好主意,因为它会使代码不可预测且难以阅读。请简化属性

    如果您只需调用一个方法就可以解密属性,那么它在代码中真正为您提供了什么额外的安全性

    如果您仍然需要一个
    Decrypt()
    将建议您创建返回解密值的解密方法,如
    GetUnencryptedCode()
    等,它也可以是一个扩展方法,但仍然不是一个可读属性


    根据您的使用情况,您还应该考虑使用
    SecureString

    您还可以分享您的EncryptionSerializer当前的外观吗?您好,我的Encryption Serializer只是实现了IBMOnSerializer。我从来都无法完成它,因为我需要访问另一个字段来获取密钥信息。让我重新开始尽可能多地重复一遍,看看是否可以发布要点。Hello@marcofo88,要点如下:您可以看到,我的计划是提取BSON文档中已有的另一个属性,然后使用它加密当前值。问题是,无法从BSON文档中获取任何其他属性。仅供参考,有Ruby Gems已经做到了这一点。我想构建一个任何人都可以使用的可插拔组件,只要他们设置了主密钥和内容加密密钥。你好,Jonas,我理解这一点。我最终手动完成了这项工作。我的目标是实现自动化,以便有人可以简单地向任何对象添加可插拔接口,然后提供主密钥Uri以及内容加密密钥(可通过iEntryptable接口获得)然后简化保存过程,无需额外的仪式。是的,我也了解解密过程。我的计划是默认情况下不解密,即默认情况下在属性中放入加密值,并要求额外的请求进行解密。自动加密是关键。请也查看我上面的评论,有Ruby Gems我已经这样做了,我正试图在C#中复制它。
    public sealed class Mapper
    {
        public void Map(Assembly assembly)
        {
        var encryptableTypes = assembly.GetTypes().Where(p =>
            typeof(IEncryptable).IsAssignableFrom(p) && p.IsClass && !p.IsInterface && !p.IsValueType &&
            !p.IsAbstract).ToList();
    
        if (encryptableTypes.Any())
        {
            foreach (var encryptableType in encryptableTypes)
            {
                Map(encryptableType);
            }
        }
    
    }
    
    private void Map(Type documentType)
    {
        var properties =
            documentType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        if (properties.Length <= 0)
        {
            return;
        }
    
        foreach (var property in properties)
        {
            RegisterEncrpytionSerializer(property, typeof(EncryptAttribute), documentType);
        }
    }
    
    private void RegisterEncrpytionSerializer(PropertyInfo property, Type encryptAttributeType, Type documentType)
    {
        var encryptAttributes = property.GetCustomAttributes(encryptAttributeType, false).ToList();
        if (!encryptAttributes.Any()) return;
    
        var memberMap = BsonClassMap.LookupClassMap(documentType).GetMemberMap(property.Name);
        memberMap?.SetSerializer(new EncryptionSerializer());
    }
    
    private void RegisterEncrpytionSerializer(PropertyInfo property, Type encryptAttributeType, Type documentType)
        {
            var encryptAttributes = property.GetCustomAttributes(encryptAttributeType, false).ToList();
            if (!encryptAttributes.Any()) return;
    
            var classMapDefinition = typeof(BsonClassMap<>);
            var classMapType = classMapDefinition.MakeGenericType(documentType);
            var classMap = (BsonClassMap)Activator.CreateInstance(classMapType);
            classMap.AutoMap();
            var memberMap = classMap.GetMemberMap(property.Name);
            memberMap?.SetSerializer(new KeyVaultEncryptionSerializer(memberMap.ElementName));
        }