在 NHibernate 中始终加密映射



目前我正在使用SQL Server 2016来利用Always Encrypted功能。我应该加密几列。我已经用SQL Server加密了这些列。NHibernate可以轻松地从SQL Server读取数据,但是当它尝试在数据库中插入数据时,它将抛出如下所示的exe:

操作数类型冲突:nvarchar(4000) 使用 (encryption_type = 加密 "确定性",encryption_algorithm_name = "AEAD_AES_256_CBC_HMAC_SHA_256", column_encryption_key_name = "CEK_Auto1",column_encryption_key_database_name = "EncTest")是 与 nvarchar(250) 不兼容,使用 (encryption_type = 加密 "确定性",encryption_algorithm_name = "AEAD_AES_256_CBC_HMAC_SHA_256", column_encryption_key_name = "CEK_Auto1", column_encryption_key_database_name = "EncTest")

这是我对NHibernate中特定列的列映射:

<column name="DisableTxt" length="100" sql-type="NVarChar" />

我应该在hbm文件中定义什么映射?

我找到了这个问题的解决方案,首先我想描述一下为什么NHibernate不能在Always Encrypted功能中使用Encrypted Columns

当我们在连接字符串中启用AlwaysEncrypted时,ADO.NETsp_describe_parameter_encryption任何数据库操作之前自动执行存储过程,以确定哪些参数对应于使用"始终加密"功能保护的数据库列。此 sp 对字段的长度很敏感,如果指定的参数长度不等于列长度,SQL Server 将给出以下错误:

操作数类型冲突:nvarchar(4000) 使用 (encryption_type = 加密 "确定性",encryption_algorithm_name = "AEAD_AES_256_CBC_HMAC_SHA_256", column_encryption_key_name = "CEK_Auto1",column_encryption_key_database_name = "EncTest")是 与 nvarchar(250) 不兼容,使用 (encryption_type = 加密 "确定性",encryption_algorithm_name = "AEAD_AES_256_CBC_HMAC_SHA_256", column_encryption_key_name = "CEK_Auto1", column_encryption_key_database_name = "EncTest")

发生这种情况是因为NHibernate始终为NVarchar列定义4000的参数大小(如果列长度不是NVarchar(max))。所以想象一下,我们有一个长度为30的列,但NHibernate为指定列定义一个长度为4000的参数。NHibernate为什么要这样做?

如果您查看SqlClientDriver.cs源代码上的第 146 行Nhibernate您将看到以下评论:

不要使用来自 SqlType,因为 LIKE 表达式需要/
/更大的列。 https://nhibernate.jira.com/browse/NH-3036

那么我们如何解决这个问题呢?我们可以为定义准确参数长度的NHibernate创建一个新Driver。(当然,如果你不在乎%%喜欢的表情)。(我已经在NHiberate 3.x中使用了此方法)

public class NewDriver : NHibernate.Driver.Sql2008ClientDriver
{
public override IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)
{
IDbCommand command = base.GenerateCommand(type, sqlString, parameterTypes);
NewDirver.SetParameterSizes(command.Parameters, parameterTypes);
return command;
}
public static void SetParamterSizes(IDataParameterCollection parameters, SqlType[] parameterTypes)
{
for(int index=0;index<parameters.Count;++index)
{
NewDriver.SetVariableLengthParameterSize((IDbDataParameter)parameters[index], parameterTypes[index]);
}
}
public static void SetVariableLengthParmaeterSize(IDbDataParameter dbParam, SqlType sqlType)
{
SqlClientDriver.SetDefaultParameterSize(dbParam, sqlType);
if(sqlType.LengthDefined && !IsText(dbParam, sqlType) && !IsBlob(dbParam, sqlType))
{
dbParam.Size = sqlType.Length;
}
if(sqlType.PrecesionsDefined)
{
dbParam.Precision = sqlType.Precision;
dbParam.Scale = sqlType.Scale;
}
}

}

相关内容

  • 没有找到相关文章

最新更新