Мне нужно зашифровать значение определенного набора полей при хранении в БД.Я использую LINQ-to-SQL.
Мой подход: прозрачно зашифровать значение соответствующих свойств в объекте перед его записью в БД.
Я уже написал перехватчикс помощью Castle Dynamic Proxy, который зашифрует соответствующее свойство на установщике и расшифрует его на получателе.Вот как я это использую:
var secretEntity = <Get a SecretEntity from the DataContext>;
ProxyGenerator pg = new ProxyGenerator();
// (Typing from memory here, so excuse possible method errors, but you get the gist)
// Reassign to now reference the dynamic proxy.
secretEntity = pg.CreateProxyWithTarget (secretEntity , new EncryptionInterceptor());
secretEntity.BigSecret = "Silentium"; // Does the encryption via the interceptor.
var decryptedSecret = secretEntity.BigSecret; // Does the decryption via the interceptor.
Теперь все это прекрасно работает, но я не хочу вручную оборачивать каждый экземпляр SecretEntity в динамический прокси.Поэтому я ищу способ автоматизировать это, чтобы, когда бы я ни получал экземпляр SecretEntity, он уже был включен в прокси.
Есть ли способ сделать это, каким-то образом подключившись к LINQ-to-SQL DataContext, чтобы он возвращал прокси?
Я использую MVC, поэтому я использую модели представлений для отображения своих данных и использую AutoMapper для сопоставления объектов и моделей представлений.Поэтому я подумал, что если подход DataQtext LINQ-to-SQL не работает, возможно, можно было бы подключиться к подпрограмме отображения и обернуть объекты в прокси, прежде чем они будут сопоставлены с моделями представления.Поэтому я был очень рад найти метод с названием BeforeMap при использовании AutoMapper.Поэтому я попытался
.BeforeMap ((se, sevm) => se = pg.CreateProxyWithTarget (se, new EncryptionInterceptor()));
// (Again, typing from memory).
Но не повезло.Я предполагаю, что это потому, что переназначение ссылки «se» на прокси не имеет эффекта после завершения запуска метода BeforeMap.
При создании нового SecretEntity я мог автоматизировать процесс переноса прокси с помощью Ninject, но Ninjectне будет работать с существующими объектами, которые я получаю из DataContext.
Моя прогулка с Castle Dynamic Proxy занимает всего пару часов, и AutoMapper не знает меня намного лучше.Поэтому я надеюсь, что кто-нибудь может дать мне быстрый указатель, где искать.
Спасибо.
Редактировать
Для полноты картины я подумалЯ бы добавил реализацию моего перехватчика для тех, кому это может быть интересно.Не зная Castle Dynamic Proxy так хорошо, я уверен, что мог бы быть лучший способ обработки перехвата и определения, является ли он геттером или сеттером, и т. Д. Вот это:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;
using TunedIn.Base.Model;
using TunedIn.Base.Ninject;
using TunedIn.Base.Extensions.StringExtensions;
namespace TunedIn.Base.Encryption
{
public class PropertyEncryptionInterceptor : IInterceptor
{
public void Intercept (IInvocation invocation)
{
IPersonEncryptedFields p = invocation.InvocationTarget as IPersonEncryptedFields;
if (p == null)
throw new ApplicationException ("{0} expects the InvocationTarget of the dynamic proxy binding to implement {1}, but {2} does not.".FormatI (typeof (PropertyEncryptionInterceptor).FullName, typeof (IPersonEncryptedFields).FullName, invocation.InvocationTarget.GetType ().FullName));
if (invocation.Method.Name.StartsWith ("set_"))
{
string val = (string)invocation.GetArgumentValue (0);
val = Kernel.Get<IStringCrypto> ().Encrypt (val);
invocation.SetArgumentValue (0, val);
invocation.Proceed ();
}
else if (invocation.Method.Name.StartsWith ("get_"))
{
invocation.Proceed ();
string ret = invocation.ReturnValue.ToString ();
ret = Kernel.Get<IStringCrypto> ().Decrypt (ret);
invocation.ReturnValue = ret;
}
else
invocation.Proceed ();
}
}
}