2012-02-13 16 views
5

आप निम्न कोड के साथ समवर्ती समस्या को कैसे हल करेंगे? इस उदाहरण में, हम क्यों जानना चाहते हैं उपयोगकर्ता प्रमाणीकरण विफल रहा। समस्या यह है कि यह कोड डेटाबेस में दो अलग-अलग कॉल करता है, लेकिन हम एक वैचारिक लेनदेन के अंदर पूरी विधि को करना चाहते हैं। विशेष रूप से हम isolation में रूचि रखते हैं। हम प्रमाणीकरण विफलता के कारण को निर्धारित करने से पहले हमारे पढ़ने को प्रभावित करने के लिए इस विधि के निष्पादन के दौरान समवर्ती लिखना नहीं चाहते हैं।एकाधिक, स्वतंत्र डेटाबेस लेनदेन के साथ Concurrency मुद्दों?

कुछ समाधान दिमाग में आते हैं: Thread Locking, TransactionScope और Optimistic Locking। मुझे वास्तव में आशावादी लॉकिंग का विचार पसंद है, क्योंकि मुझे लगता है कि संघर्ष दुर्लभ होने की संभावना है, लेकिन ऐसा करने के लिए .NET में कुछ भी नहीं बनाया गया है, है ना?

इसके अलावा - क्या इस मामले में वास्तव में इस बारे में चिंतित होना कुछ है? जब इस पर विचार करने के लिए इस तरह के महत्वपूर्ण मुद्दे हैं और वे कब नहीं हैं? समाधान को लागू करने के लिए क्या विचार किया जाना चाहिए? प्रदर्शन? ताला की अवधि? विवादों की संभावना कितनी है?

संपादित करें: Aristos 'जवाब समीक्षा करने के बाद, मुझे लगता है कि मैं क्या कर रहा हूँ वास्तव में के बाद "snapshot" प्रमाणित विधि के लिए अलगाव स्तर के कुछ प्रकार है।

public MembershipStatus Authenticate(string username, string password) 
    { 
     MembershipUser user = Membership.GetUser(username); 
     if (user == null) 
     { 
      // user did not exist as of Membership.GetUser 
      return MembershipStatus.InvalidUsername; 
     } 

     if (user.IsLockedOut) 
     { 
      // user was locked out as of Membership.GetUser 
      return MembershipStatus.AccountLockedOut; 
     } 

     if (Membership.ValidateUser(username, password)) 
     { 
      // user was valid as of Membership.ValidateUser 
      return MembershipStatus.Valid; 
     } 

     // user was not valid as of Membership.ValidateUser BUT we don't really 
     // know why because we don't have ISOLATION. The user's status may have changed 
     // between the call to Membership.GetUser and Membership.ValidateUser. 
     return MembershipStatus.InvalidPassword; 
    } 
mutex
+1

मुझे यकीन है कि तुम सच में अलगाव के बारे में यहाँ चिंता करने की जरूरत नहीं है। 'GetUser' और' ValidateUser' 'पर कॉल के बीच उपयोगकर्ता को हटा दिया जाएगा या लॉक हो जाने की संभावना क्या है? और इस बिंदु पर, आपको इस जानकारी को उपयोगकर्ता को किसी भी तरह से उजागर नहीं करना चाहिए। यदि आप "गलत पासवर्ड" बनाम "उपयोगकर्ता मौजूद नहीं हैं" बनाम "खाता लॉक आउट" के लिए अलग-अलग संदेश दिखाते हैं, तो कोई भी व्यक्ति आपकी साइट हैक करने का प्रयास कर रहा है, वह वैध उपयोगकर्ता नामों की सूची प्राप्त करने के लिए उस जानकारी का लाभ उठा सकता है।आप यह नहीं चाहते हैं, क्योंकि उन उपयोगकर्ता नाम आपके बुनियादी ढांचे में कुछ अन्य भेद्यता का शोषण करने में सहायक हो सकते हैं। प्रतिक्रिया के लिए –

+0

+1। मैंने शायद यहां एक खराब उदाहरण का उपयोग किया है (हालांकि मैं "अवैध प्रमाण-पत्र" और "खाता लॉक आउट" के बीच अंतर करने की योजना बना रहा था और शायद मुझे उस पर पुनर्विचार करना होगा)। मुझे बस इस तथ्य को पसंद नहीं है कि डेटा मेरे नीचे बदल सकता है! Concurrency मुश्किल है! क्या होगा यदि मुझे डेटा को लगातार बनाए रखने की आवश्यकता है, तो आप क्या सुझाव देंगे? इस प्रश्न का उत्तर देने और सत्र की जानकारी के लिए समय लेने के लिए – Brandon

उत्तर

1

मेरी पढ़ने here और here के आधार पर यह, अपने पूरे विधि लपेटकर स्वचालित रूप से एक आम लेनदेन में अपने डेटाबेस कॉल भर्ती चाहिए एक System.Transactions.TransactionScope की तरह लगता है, जिसके परिणामस्वरूप पूरे लेनदेन के दायरे में लेनदेन सुरक्षा में।

आप इस तरह कुछ करना चाहता हूँ चाहते हैं:

public MembershipStatus Authenticate(string username, string password) 
{ 
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot })) 
    { 
    MembershipUser user = Membership.GetUser(username); 
     if (user == null) 
     { 
      // user did not exist as of Membership.GetUser 
      return MembershipStatus.InvalidUsername; 
     } 

     if (user.IsLockedOut) 
     { 
      // user was locked out as of Membership.GetUser 
      return MembershipStatus.AccountLockedOut; 
     } 

     if (Membership.ValidateUser(username, password)) 
     { 
      // user was valid as of Membership.ValidateUser 
      return MembershipStatus.Valid; 
     } 

     // user was not valid as of Membership.ValidateUser BUT we don't really 
     // know why because we don't have ISOLATION. The user's status may have changed 
     // between the call to Membership.GetUser and Membership.ValidateUser. 
     return MembershipStatus.InvalidPassword; 
    } 
} 
+0

+1। मुझे अपने स्वयं के सदस्यता प्रदाता को लागू करने की आवश्यकता क्यों होगी? क्या मैं सिर्फ लेनदेनस्कोप वर्ग का उपयोग नहीं कर सकता "जिसमें लेनदेन स्वचालित रूप से आधारभूत संरचना द्वारा प्रबंधित किया जाता है"? – Brandon

+0

@ ब्रैंडन क्षमा करें, जवाब देने में इतना समय लगा - मैं इसका जवाब देने से पहले कुछ शोध करना चाहता था। मैंने लेनदेनस्कोप के उपयोग को प्रतिबिंबित करने के लिए अपना उत्तर अपडेट कर लिया है। प्रतिक्रिया के लिए –

+0

धन्यवाद। मैं इसे स्वीकार्य उत्तर के रूप में चिह्नित कर रहा हूं, ज्यादातर मेरे प्रश्न पर आपकी पहली टिप्पणी के लिए (शायद मुझे यह शुरू करने के लिए नहीं करना चाहिए और यहां तक ​​कि अगर मैं वास्तव में कोई मुद्दा नहीं चाहता था)। – Brandon

1

मैं का उपयोग करेगा के रूप में parametre ताला लगा है, इसलिए केवल एक ही उपयोगकर्ता थोड़ी देर के लिए बाहर लॉक कर सकते हैं हो सकता है नाम का उपयोग कर। यह मेरे लिए एक कंप्यूटर के लिए अधिक सुरक्षित है क्योंकि म्यूटेक्स के साथ मैं विभिन्न पूल, या वेब कॉल से सभी संभावित धागे को कैप्चर कर सकता हूं।

public MembershipStatus AuthenticateLock(string username, string password) 
{ 
    if(string.IsNullOrEmpty(username)) 
     return MembershipStatus.InvalidUsername; 

    // TODO: Here you must check and clear for non valid characters on mutex name 
    using (var mutex = new Mutex (false, username)) 
    { 
     // possible lock and wait, more than 16 seconds and the user can go... 
     mutex.WaitOne (TimeSpan.FromSeconds(16), false); 

     // here I call your function anyway ! and what ever done... 
     // at least I get a result 
     return Authenticate(username, password) 
    } 
} 

अधिक टिप्पणियां: डेटाबेस के लिए दोनों Membership.ValidateUser और Membership.GetUser कर कॉल।

लेकिन आप पृष्ठ हैं जो यह कॉल करने के लिए मानक asp.net सत्र का उपयोग करें और इस पैरामीटर, तो पेज पूरी तरह से तैयार ताला एक अन्य इसलिए मुझे लगता है इस की जरूरत के लिए कोई मौका नहीं है कि वहाँ को प्रभावित करता है, तो म्यूटेक्स कॉल क्योंकि सत्र का लॉक सिंक्रनाइज़ करने और इस भाग के लिए पर्याप्त है। मुझे याद दिलाता है कि सत्र पृष्ठ से सभी उपयोगकर्ताओं के लिए शुरुआत से अंत तक लॉक कर रहा है।

सत्र ताला के बारे में: Replacing ASP.Net's session entirely

jQuery Ajax calls to web service seem to be synchronous

+0

+1। तो आप थ्रेड लॉकिंग का सुझाव दे रहे हैं। थ्रेड लॉकिंग एक प्रकार का "मुलायम" अलगाव प्रदान करता है, लेकिन यदि आपके पास साझा संसाधन तक पहुंचने का प्रयास करने वाली एकाधिक प्रक्रियाएं (धागे नहीं) हैं तो उपयोगी नहीं होंगे। मुझे लगता है कि मैं वास्तव में क्या कर रहा हूं प्रमाणीकरण विधि के लिए "स्नैपशॉट" अलगाव स्तर का कुछ प्रकार है। – Brandon

+1

@ ब्रैंडन मैं जिस म्यूटेक्स लॉक का उपयोग करता हूं वह कई प्रक्रियाओं के लिए हेलफुल है! लेकिन मैं कहता हूं कि यदि आप इस फ़ंक्शन में अपनी सभी कॉल में सत्र का उपयोग करते हैं, तो आपको इसकी भी आवश्यकता नहीं है। सत्र लॉक सभी पृष्ठों को तैयार करें, इसलिए आपको दूसरे लॉक की आवश्यकता नहीं है। – Aristos

+0

दिलचस्प! मुझे नहीं पता था कि "नामित सिस्टम म्यूटेक्स पूरे ऑपरेटिंग सिस्टम में दिखाई दे रहे हैं, और प्रक्रियाओं की गतिविधियों को सिंक्रनाइज़ करने के लिए इस्तेमाल किया जा सकता है।" तो मुझे लगता है कि सीमा पीसी/ओएस है, उदा। आप एकाधिक पीसी/ओएस में म्यूटेक्स के साथ प्रक्रियाओं को सिंक्रनाइज़ नहीं कर सकते हैं? जवाब देने के लिए समय लेने के लिए – Brandon

संबंधित मुद्दे