假设有User表

public class User : Entity<int>
{
public int Id { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
public string IdentificationNumber { get; set; }
}

其中有身份证号码IdentificationNumber列,需要加密存储,该如何实现?

![在这里插入图片描述](https://img-blog.csdnimg.cn/a9edb9793cc841ff91391ec7d4d298d7.png

创建一个值转换器,继承ValueConverter<TModel, string>类型。其中泛型TModel为实体中属性的类型。

转换器将实体中属性类型,通过AES加密算法,转换为Base64编码字符串类型,存储到数据库中。当从数据库中读取数据时,再通过AES解密算法,将Base64编码字符串类型转换为实体中属性类型。

若实体类型为byte[],则不需要转换为Base64编码字符串类型,直接对二进制数据进行加密和解密。此转换器可以用于加密存储图片、文件等二进制数据。

AES加密算法是一种对称加密算法,加密和解密使用相同的密钥。在加密和解密时,需要指定密钥、初始向量、盐值等参数。在转换器中,将这些参数设置为静态属性,方便在使用时,进行修改。

代码如下:

public class EncryptionConverter<TModel> : ValueConverter<TModel, string>
{ public const int DefaultKeysize = 256; public static string DefaultPassPhrase { get; set; } public static byte[] DefaultInitVectorBytes { get; set; } public static byte[] DefaultSalt { get; set; }
public EncryptionConverter()
: base(
x => Encrypt(x),
x => Decrypt(x))
{
DefaultPassPhrase = "gsKnGZ041HLL4IM8";
DefaultInitVectorBytes = Encoding.ASCII.GetBytes("jkE49230Tf093b42");
DefaultSalt = Encoding.ASCII.GetBytes("hgt!16kl");
} private static string Encrypt(TModel input)
{
try
{
byte[] inputData = input switch
{
string => Encoding.UTF8.GetBytes(input.ToString()),
byte[] => input as byte[],
_ => null,
}; using (var password = new Rfc2898DeriveBytes(DefaultPassPhrase, DefaultSalt))
{
var keyBytes = password.GetBytes(DefaultKeysize / 8);
using (var symmetricKey = Aes.Create())
{
symmetricKey.Mode = CipherMode.CBC;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, DefaultInitVectorBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(inputData, 0, inputData.Length);
cryptoStream.FlushFinalBlock();
var cipherTextBytes = memoryStream.ToArray();
var rawString = Convert.ToBase64String(cipherTextBytes);
return rawString; }
}
}
}
}
}
catch (Exception ex)
{
LogHelper.LogException(ex);
return input.ToString();
} } private static TModel Decrypt(string input)
{
try
{
var cipherTextBytes = Convert.FromBase64String(input); using (var password = new Rfc2898DeriveBytes(DefaultPassPhrase, DefaultSalt))
{
var keyBytes = password.GetBytes(DefaultKeysize / 8);
using (var symmetricKey = Aes.Create())
{
symmetricKey.Mode = CipherMode.CBC;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, DefaultInitVectorBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
var plainTextBytes = new byte[cipherTextBytes.Length];
int totalDecryptedByteCount = 0;
while (totalDecryptedByteCount < plainTextBytes.Length)
{
var decryptedByteCount = cryptoStream.Read(
plainTextBytes,
totalDecryptedByteCount,
plainTextBytes.Length - totalDecryptedByteCount
); if (decryptedByteCount == 0)
{
break;
} totalDecryptedByteCount += decryptedByteCount;
}
byte[] outputData = null;
if (typeof(TModel) == typeof(string))
{
outputData = Encoding.UTF8.GetBytes(plainTextBytes.ToString());
}
else if (typeof(TModel) == typeof(byte[]))
{
outputData = plainTextBytes as byte[];
}; var rawString = Encoding.UTF8.GetString(outputData, 0, totalDecryptedByteCount); return (TModel)Convert.ChangeType(rawString, typeof(TModel)); }
}
}
}
} }
catch (Exception ex)
{
// 记录异常
// LogHelper.LogException(ex);
return (TModel)Convert.ChangeType(input, typeof(TModel));
} }
}

DbContext中,重写OnModelCreating方法,为User表的IdentificationNumber列,添加值转换器。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(c => c.IdentificationNumber).HasConversion<EncryptionConverter<string>>();
}

再次调用Add方法插入数据时,可以看到IdentificationNumber列已被加密了

在EF Core中为数据表按列加密存储的更多相关文章

  1. 9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)

    原文地址:http://www.entityframeworktutorial.net/code-first/dataannotation-in-code-first.aspx EF 6 Code-F ...

  2. 文章翻译:ABP如何在EF core中添加数据过滤器

    原文地址:https://aspnetboilerplate.com/Pages/Documents/Articles%5CHow-To%5Cadd-custom-data-filter-ef-cor ...

  3. EF Core中如何正确地设置两张表之间的关联关系

    数据库 假设现在我们在SQL Server数据库中有下面两张表: Person表,代表的是一个人: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ...

  4. 20.1翻译系列:EF 6中自动数据迁移技术【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/automated-migration-in-code-first.aspx EF 6 ...

  5. 9.4 翻译系列:EF 6以及 EF Core中的NotMapped特性(EF 6 Code-First系列)

    原文链接:http://www.entityframeworktutorial.net/code-first/notmapped-dataannotations-attribute-in-code-f ...

  6. EF Core中如何通过实体集合属性删除从表的数据

    假设在数据库中有两个表:Person表和Book表,Person和Book是一对多关系 Person表数据: Book表数据: 可以看到数据库Book表中所有的数据都属于Person表中"F ...

  7. EF Core 中多次从数据库查询实体数据,DbContext跟踪实体的情况

    使用EF Core时,如果多次从数据库中查询一个表的同一行数据,DbContext中跟踪(track)的实体到底有几个呢?我们下面就分情况讨论下. 数据库 首先我们的数据库中有一个Person表,其建 ...

  8. EF Core中如何设置数据库表自己与自己的多对多关系

    本文的代码基于.NET Core 3.0和EF Core 3.0 有时候在数据库设计中,一个表自己会和自己是多对多关系. 在SQL Server数据库中,现在我们有Person表,代表一个人,建表语句 ...

  9. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    Paul Hiles: 3 ways to avoid an anemic domain model in EF Core 1.引言 在使用ORM中(比如Entity Framework)贫血领域模型 ...

  10. EF Core中执行Sql语句查询操作之FromSql,ExecuteSqlCommand,SqlQuery

    一.目前EF Core的版本为V2.1 相比较EF Core v1.0 目前已经增加了不少功能. EF Core除了常用的增删改模型操作,Sql语句在不少项目中是不能避免的. 在EF Core中上下文 ...

随机推荐

  1. Java基础Day7-值传递和引用传递

    一.值传递 Java都是值传递. 值传递:是指在调用函数时,将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,就不会影响到实际参数. 值传递是对基本数据类型而言. 二.引用传递 引用传递 ...

  2. 在脚手架中使用React

    1.导入react 和react-dom 两包 import React from 'react' import ReactDOM from 'react-dom' 2.调用React.createE ...

  3. curl post请求body体内传参数

    1. 传参格式 json function post_http($array='',$url) { $ch = curl_init(); $header = array('Content-Type: ...

  4. html超链接相关代码

    1. <IDOCTYPE html>< html><head><title>图像和超链接</title><meta http-equi ...

  5. How to Install VMware Tools on CentOS 6.5

    yum install perl gcc make kernel-headers kernel-devel -y [root@centos6 vmware-tools-distrib]# ./vmwa ...

  6. 京东薅羊毛脚本-Docker

    一.安装好docker,然后创建容器: 注1:如果是旁路由,建议用--network host \代替-p 5678:5678 \这一行. 注2:如果想要看到lxk0301大佬的js脚本,并且重新部署 ...

  7. H. Permutation Counting 判环,计数,拓扑

    H. Permutation Counting 2022/7/28 传送门:https://codeforces.com/group/5zHJ4CTyoU/contest/392060/problem ...

  8. Java-01enum常量特定方法

    OnJava8-Enum-常量特定方法 用枚举实现责任链模式 责任链(Chain Of Responsibility)设计模式先创建了一批用于解决目标问题的不同方法,然后将它们连成一条"链& ...

  9. 痞子衡嵌入式:分享一个i.MXRT系列配套DRAM压力测试上位机工具(i.MXRT DRAM Tester)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦SE团队制作的i.MXRT配套DRAM压力测试上位机工具. 事情源于痞子衡的技术交流群里的提问,有群友在恩智浦官方技术公众号 [恩 ...

  10. Java线程池和Spring异步处理高级篇

    开发过程中我们会遇到很多使用线程池的场景,例如异步短信通知,异步发邮件,异步记录操作日志,异步处理批量Excel解析.这些异步处理的场景我们都可以把它放在线程池中去完成,当然还有很多场景也都可以使用线 ...