पोस्ट
NHibernate लिस्नर्स (इंटरसेप्टर्स) के साथ पारदर्शी एन्क्रिप्शन का कार्यान्वयन
3 नवंबर 2014 • 5 मिनट पढ़ना

क्या आपको कभी डेटाबेस में डेटा को एन्क्रिप्ट करना पड़ा है? इस पोस्ट में, मैं nHibernate लिस्नर्स का उपयोग करके आपके डेटाबेस से आने वाले और जाने वाले डेटा को एन्क्रिप्ट और डिक्रिप्ट करने का तरीका जानूंगा। क्रिप्टोग्राफी आपके एप्लिकेशन के लिए पारदर्शी होगी।
आप ऐसा क्यों करना चाहेंगे? SQL Server में एन्क्रिप्शन उत्पाद में बेक्ड है। यह सच है, लेकिन यदि आप क्लाउड में जा रहे हैं और SQL Azure का उपयोग करना चाहते हैं तो आपको किसी प्रकार की क्रिप्टोग्राफी रणनीति की आवश्यकता होगी। SQL Azure डेटाबेस एन्क्रिप्शन का समर्थन नहीं करता है।
nHibernate लिस्नर क्या है? मैं लिस्नर को कोड के एक टुकड़े के रूप में सोचता हूं जिसे मैं nHibernate persistence और डेटा हाइड्रेशन जीवनचक्र में विशिष्ट एक्स्टेंसिबिलिटी पॉइंट्स में इंजेक्ट कर सकता हूं।
इस लेखन के समय nHibernate में निम्नलिखित एक्स्टेंसिबिलिटी पॉइंट्स उपलब्ध हैं।
IAutoFlushEventListener
IDeleteEventListener
IDirtyCheckEventListener
IEvictEventListener
IFlushEntityEventListener
IFlushEventListener
IInitializeCollectionEventListener
ILoadEventListener
ILockEventListener
IMergeEventListener
IPersistEventListener
IPostCollectionRecreateEventListener
IPostCollectionRemoveEventListener
IPostCollectionUpdateEventListener
IPostDeleteEventListener
IPostInsertEventListener
IPostLoadEventListener
IPostUpdateEventListener
IPreCollectionRecreateEventListener
IPreCollectionRemoveEventListener
IPreCollectionUpdateEventListener
IPreDeleteEventListener
IPreInsertEventListener
IPreLoadEventListener
IPreUpdateEventListener
IRefreshEventListener
IReplicateEventListener
ISaveOrUpdateEventListener
यह सूची व्यापक है।
पारदर्शी क्रिप्टोग्राफी को लागू करने के लिए, हमें डेटा को एन्क्रिप्ट और डिक्रिप्ट करने के लिए सही जगह खोजनी होगी। डेटा को एन्क्रिप्ट करने के लिए हम IPostInsertEventListener
और IPostUpdateEventListener
का उपयोग करेंगे। इन इवेंट्स के साथ हम डेटाबेस में जाने वाले नए डेटा और अपडेटेड डेटा को पकड़ेंगे। डिक्रिप्ट करने के लिए, हम IPreLoadEventListener
का उपयोग करेंगे।
इस प्रदर्शन के लिए हम एन्क्रिप्ट और डिक्रिप्ट करने के लिए DatabaseCryptography
क्लास का उपयोग करेंगे। क्रिप्टोग्राफी कार्यान्वयन इस लेख के लिए महत्वपूर्ण नहीं है।
IPreLoadEventListener
public class PreLoadEventListener : IPreLoadEventListener
{
readonly DatabaseCryptography _crypto = new DatabaseCryptography();
///
/// Called when [pre load].
///
///The event. public void OnPreLoad(PreLoadEvent @event)
{
_crypto.DecryptProperty(@event.Entity, @event.Persister.PropertyNames, @event.State);
}
}
IPreInsertEventListener
public class PreInsertEventListener : IPreInsertEventListener
{
readonly DatabaseCryptography _crypto = new DatabaseCryptography();
///
/// Return true if the operation should be vetoed
///
///The event. /// true if XXXX, false otherwise.
public bool OnPreInsert(PreInsertEvent @event)
{
_crypto.EncryptProperties(@event.Entity, @event.State, @event.Persister.PropertyNames);
return false;
}
}
IPreUpdateEventListener
public class PreUpdateEventListener : IPreUpdateEventListener
{
readonly DatabaseCryptography _crypto = new DatabaseCryptography();
///
/// Return true if the operation should be vetoed
///
///The event. /// true if XXXX, false otherwise.
public bool OnPreUpdate(PreUpdateEvent @event)
{
_crypto.EncryptProperties(@event.Entity, @event.State, @event.Persister.PropertyNames);
return false;
}
}
यह ध्यान रखना महत्वपूर्ण है कि IPreUpdateEventListener
और IPreInsertEventListener
दोनों को false रिटर्न करना चाहिए, अन्यथा insert/update इवेंट रद्द हो जाएगा।
अब जब हमने लिस्नर्स को लागू कर दिया है तो हमें उन्हें nHibernate के साथ रजिस्टर करना होगा। मैं FluentNHibernate
का उपयोग कर रहा हूं इसलिए यह अलग होगा यदि आप raw nHibernate का उपयोग कर रहे हैं।
SessionFactory
public class SessionFactory
{
///
/// Creates the session factory.
///
/// ISessionFactory.
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012
.ConnectionString(c => c
.FromConnectionStringWithKey("DefaultConnection")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf())
.ExposeConfiguration(s =>
{
s.SetListener(ListenerType.PreUpdate, new PreUpdateEventListener());
s.SetListener(ListenerType.PreInsert, new PreInsertEventListener());
s.SetListener(ListenerType.PreLoad, new PreLoadEventListener());
})
.BuildConfiguration()
.BuildSessionFactory();
}
जब एप्लिकेशन स्तर पर डेटा को डिक्रिप्ट और एन्क्रिप्ट करते हैं तो यह डेटाबेस में डेटा को बेकार बना देता है। एन्क्रिप्टेड फील्ड्स के मानों को पढ़ने के लिए आपको डेटा को वापस एप्लिकेशन में लाना होगा। हम उन फील्ड्स को सीमित करना चाहते हैं जो एन्क्रिप्टेड हैं और हम केवल स्ट्रिंग मानों को एन्क्रिप्ट करना चाहते हैं। स्ट्रिंग मानों के अलावा कुछ भी एन्क्रिप्ट करना चीजों को जटिल बना देता है। कुछ भी नहीं कह रहा कि हम तारीखों को एन्क्रिप्ट नहीं कर सकते, लेकिन ऐसा करने के लिए डेटाबेस में डेट फील्ड को एन्क्रिप्टेड डेटा रखने के लिए स्ट्रिंग (nvarchar या varchar) फील्ड बनना होगा, एक बार जब हम ऐसा करते हैं तो हम डेटाबेस से डेट फील्ड पर ऑपरेट करने की क्षमता खो देते हैं।
यह पहचानने के लिए कि हम कौन से फील्ड्स को एन्क्रिप्टेड और डिक्रिप्टेड करना चाहते हैं, मैं मार्कर एट्रिब्यूट्स का उपयोग करूंगा।
Encrypt Attribute
public class EncryptAttribute : Attribute
{
}
Decrypted Attribute
public class DecryptAttribute : Attribute
{
}
EncryptAttribute
और DecryptedAttribute
को एक्शन में देखने के लिए हम DatabaseCryptography
क्लास में झांकेंगे।
DatabaseCryptography
public class DatabaseCryptography
{
private readonly Crypto _crypto = ObjectFactory.GetInstance();
///
/// Encrypts the properties.
///
///The entity. ///The state. ///The property names.
public void EncryptProperties(object entity, object[] state, string[] propertyNames)
{
Crypt(entity, propertyNames, s = >
_crypto.Encrypt(s),
state)
;
}
///
/// Crypts the specified entity.
///
///
///The entity. ///The state. ///The property names. ///The crypt.
private void Crypt(object entity, string[] propertyNames, Func<string, string> crypt, object[] state) where T : Attribute
{
if (entity != null)
{
var properties = entity.GetType().GetProperties();
foreach (var info in properties)
{
var attributes = info.GetCustomAttributes(typeof (T), true);
if (attributes.Any())
{
var name = info.Name;
var count = 0;
foreach (var s in propertyNames)
{
if (string.Equals(s, name, StringComparison.InvariantCultureIgnoreCase))
{
var val = Convert.ToString(state[count]);
if (!string.IsNullOrEmpty(val))
{
val = crypt(val);
state[count] = val;
}
break;
}
count++;
}
}
}
}
}
///
/// Decrypts the property.
///
///The entity. ///The state. ///The property names.
public void DecryptProperies(object entity, string[] propertyNames, object[] state)
{
Crypt(entity, propertyNames, s = >
_crypto.Decrypt(s),
state)
;
}
}
बस इतना ही। अब डेटा का एन्क्रिप्शन और डिक्रिप्शन एप्लिकेशन के लिए पारदर्शी होगा और आप अगला Facebook बनाने के अपने रास्ते पर जा सकते हैं।
लेखक: चक कॉनवे सॉफ्टवेयर इंजीनियरिंग और जेनेरेटिव AI में विशेषज्ञता रखते हैं। उनसे सोशल मीडिया पर जुड़ें: X (@chuckconway) या उन्हें YouTube पर देखें।