MongoDB C#驱动中如何向BsonSerializer特性传参实现关联字段加密
结论
你无法直接在字段级的TextSerializer中获取当前文档的departmentId值。MongoDB C# 驱动的字段级序列化器仅持有当前字段的上下文信息,不会暴露父文档的其他字段或完整实例。
可行方案
根据你的业务场景(大量字段需要应用同类加密逻辑),推荐以下几种实现方式:
- 方案1:文档级自定义序列化器
为Transaction类实现全文档自定义序列化器,在序列化/反序列化整个文档的流程中先读取departmentId,再对所有需要加解密的字段做处理。该方案逻辑直观,但如果实体数量多会存在重复代码。 - 方案2:实现序列化回调接口
让实体类实现IBsonSerialize、IBsonDeserialize接口,在默认序列化执行前插入加密逻辑、默认反序列化执行后插入解密逻辑,代码示例如下:public class Transaction : IEquatable<Transaction>, IBsonSerialize, IBsonDeserialize { [BsonId] public Guid id; [BsonElement("text")] public string text; [BsonElement("departmentid")] public Guid departmentId; public void Serialize(BsonSerializationContext context, BsonSerializationArgs args) { // 执行加密 var originalText = text; text = EncryptUtil.Encrypt(text, departmentId); // 调用默认序列化逻辑 BsonSerializer.LookupSerializer<Transaction>().Serialize(context, args, this); // 还原原字段值,避免影响后续业务逻辑 text = originalText; } public void Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { // 调用默认反序列化拿到全量字段 var instance = BsonSerializer.LookupSerializer<Transaction>().Deserialize(context, args); // 赋值基础字段 id = instance.id; departmentId = instance.departmentId; // 执行解密 text = EncryptUtil.Decrypt(instance.text, departmentId); } } - 方案3:自定义序列化约定+通用加密拦截(推荐大量字段场景使用)
- 定义标记属性
[EncryptWithField(nameof(departmentId))],打在所有需要加密的字段上 - 实现自定义
IBsonSerializationProvider,扫描实体字段的标记属性,为带标记的字段返回通用加密序列化器 - 全局注册该序列化Provider,所有符合条件的字段会自动应用加解密逻辑,无需每个实体单独编写适配代码。
- 定义标记属性
内容的提问来源于stack exchange,提问作者Ran Marciano
相关产品推荐
相关产品推荐

