यह @TheCloudlessSky द्वारा प्रस्तावित उत्तर का कार्यान्वयन उदाहरण है। मैंने सोचा कि इससे किसी को भी मदद मिलेगी जो सोच रहा था कि इसे लागू करने के बारे में कैसे जाना है।
मैं मौजूदा डेटाबेस के साथ काम कर रहा था, इसलिए मूल मॉडल वर्ग स्वचालित रूप से मेरे लिए जेनरेट किया गया था।
स्वत: निर्मित User.cs:
namespace MyApp.Model
{
public partial class User
{
public int UserId { get; set; }
public byte[] SSN { get; set; }
...
}
}
मैं अपने खुद के User.cs. बनाया (ध्यान दें कि यह ऑटो नामित उपयोगकर्ता.cs के समान नामस्थान में है और कोई कंपाइलर त्रुटियां नहीं थीं क्योंकि ऑटो जेनरेट किए गए User.cs को आंशिक वर्ग के रूप में घोषित किया गया था! इसके अलावा, मेरे स्वयं के User.cs उसी फ़ोल्डर में नहीं हो सकते फ़ाइल नाम संघर्ष की वजह से स्वत: जनरेट User.cs!)
namespace MyApp.Model
{
public partial class User
{
public string DecryptedSSN { get; set; }
...
}
}
अब जब भी मैं अपने DbContext से उपयोगकर्ता को पुनः प्राप्त करने के लिए गए थे, मैं सभी गुण स्वत: जनरेट वर्ग के साथ-साथ लोगों में परिभाषित के रूप में परिभाषित देखेंगे मेरी उन्नत कक्षा।
यहां मेरे उपयोगकर्ता रिपोजिटरी का कार्यान्वयन है।सीएस:
namespace MyApp.Model
{
public interface IUserRepository
{
User Get(int userId);
...
}
public class UserRepository : IUserRepository
{
public User GetById(int userId)
{
using (var dataContext = MyDbContext())
{
var user = dataContext.Users.Find(u => u.UserId == userId);
var decryptedSSNResult = dataContext.Decrypt(u.SSN);
user.DecryptedSSN = decryptedSSNResult.FirstOrDefault();
return user;
}
}
}
}
अब आप सोच रहे हो सकता है कि कैसे/जहाँ मैं MyDbContext.Decrypt() से मिला?
यह आपके लिए ऑटो जनरेट नहीं है। हालांकि, आप इस संग्रहीत प्रक्रिया को अपने स्वत: जेनरेट मॉडल में आयात कर सकते हैं। Context.cs फ़ाइल। (यह प्रक्रिया आधिकारिक EntityFramework आलेख में बहुत अच्छी तरह से प्रलेखित है: कैसे करें: http://msdn.microsoft.com/en-us/library/vstudio/bb896231(v=vs.100).aspx पर एक संग्रहीत प्रक्रिया (इकाई डेटा मॉडल उपकरण) आयात करें)
बस अगर आपको नहीं पता कि अंतिम परिणाम कैसा दिखना चाहिए, तो यहां है क्या स्वतः अपने Model.Context.cs में बनाया गया:
namespace MyApp.Model
{
// using statements found here
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name = MyDbContext")
{ }
public virtual ObjectResult<string> Decrypt(byte[] encryptedData)
{
var encryptedDataParameter = encryptedData != null ?
new ObjectParameter("encryptedData", encryptedData) :
new ObjectParameter("encryptedData", typeof(byte[]));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("Decrypt", encryptedDataParameter);
}
// similar function for Encrypt
}
}
यह कैसे मेरे डिक्रिप्ट संग्रहित प्रक्रिया लग रहा है जैसे:
CREATE PROCEDURE decrypt
@encryptedData VARBINARY(8000)
AS
BEGIN
OPEN SYMMETRIC KEY xxx_Key DECRYPTION BY CERTIFICATE xxx_Cert;
SELECT CAST(DECRYPTIONBYKEY(@encryptedData) AS NVARCHAR(MAX)) AS data;
CLOSE ALL SYMMETRIC KEYS;
END;
GO
प्रदर्शन विचार
अब जब मैंने आपको @TheCloudlessSky द्वारा दिए गए उत्तर का कार्यान्वयन दिखाया है, तो मैं कुछ प्रदर्शन संबंधी बिंदुओं को त्वरित रूप से हाइलाइट करना चाहता हूं।
1) प्रत्येक बार जब आप उपयोगकर्ता ऑब्जेक्ट को पुनर्प्राप्त करते हैं, तो डेटाबेस के लिए 2 ट्रिप किए जा रहे हैं। ऑब्जेक्ट को पुनर्प्राप्त करने के लिए पहली यात्रा; एसएसएन डिक्रिप्ट करने के लिए दूसरी यात्रा। यदि आप सावधान नहीं हैं तो इससे प्रदर्शन समस्याएं हो सकती हैं।
सिफारिश: ऑटो एन्क्रिप्टेड फ़ील्ड को डिक्रिप्ट न करें! ऊपर दिखाए गए मेरे उदाहरण में, जब मैं उपयोगकर्ता ऑब्जेक्ट पुनर्प्राप्त कर रहा था, तो मैंने एसएसएन को डिक्रिप्ट कर दिया। मैंने ऐसा किया था कि केवल प्रदर्शन उद्देश्यों के लिए था! खुद से पूछें कि क्या आपको वास्तव में एसएसएन की आवश्यकता है हर बार उपयोगकर्ता को पुनर्प्राप्त किया जाता है। यदि संभव हो, उत्सुक डिक्रिप्शन पर आलसी डिक्रिप्शन चुनें!
2) हालांकि मैंने यह प्रदर्शित नहीं किया है, हर बार जब आप उपयोगकर्ता ऑब्जेक्ट बनाते/अपडेट करते हैं, तो डेटाबेस में 2 ट्रिप भी किए जाएंगे। एसएसएन एन्क्रिप्ट करने के लिए पहली यात्रा; वस्तु डालने के लिए दूसरी यात्रा। यदि आप सावधान नहीं हैं तो फिर से यह प्रदर्शन समस्याओं का कारण बन सकता है।
सिफ़ारिश: इस प्रदर्शन हिट के बारे में सचेत रहें लेकिन एन्क्रिप्ट करने और एक अलग तरीके के रूप में एसएसएन के बचत प्रतिनिधि नहीं है। इसे सभी एक ऑपरेशन में रखें अन्यथा आप इसे पूरी तरह से सहेजना भूल सकते हैं। तो बनाने/अद्यतन करने की सिफारिश पुनर्प्राप्ति के विपरीत है: आलसी एन्क्रिप्शन पर उत्सुक एन्क्रिप्शन चुनें!
एक अच्छा समाधान की तरह लगता है और यदि मैं एक नया डेटाबेस बनाया तो शायद मैं इसके साथ जाऊंगा। बात यह है कि डेटाबेस बहुत बड़ा है और कई परियोजनाओं द्वारा इसका उपयोग किया जाता है, इसलिए कोड पर जाने और इसे बदलने के लिए यह एक बड़ी नौकरी होगी। – Andreas
@Andreas - ऊपर मेरा संपादन देखें। – TheCloudlessSky
सुझाव के लिए धन्यवाद। यह वास्तव में एक अच्छा विचार की तरह लग रहा था और मैंने इसे आजमाया। दुर्भाग्यवश यदि मैं तालिका से अपने सभी डिक्रिप्ट किए गए डेटा पर LINQ क्वेरी करने में सक्षम होना चाहता हूं, तो संग्रहीत प्रक्रिया को पहले निष्पादित करना होगा। यह हमेशा के लिए लेता है क्योंकि यह 250 000+ पंक्तियों के साथ 5 कॉलम के साथ प्रत्येक को डिक्रिप्ट किया जाता है। तो ऐसा कर रहा है: context.AllMembers()। जहां (x => x.MemberId == 1) बहुत लंबा लगेगा। निश्चित रूप से मैं एक एसपी कर सकता हूं जो सदस्यीय का तर्क लेता है, लेकिन अगर मैं खोजना चाहता हूं तो क्या होगा LINQ के साथ पहला नाम? शायद मैं यहां कुछ महत्वपूर्ण याद कर रहा हूं ... – Andreas