2008-12-05 8 views
18

मान लें कि मैं एक डब्ल्यूसीएफ सेवा तैयार करने पर विचार कर रहा हूं जिसका प्राथमिक उद्देश्य व्यापक सेवाओं को प्रदान करना है जिसका उपयोग तीन अलग-अलग अनुप्रयोगों द्वारा किया जा सकता है: एक सार्वजनिक चेहरा वेबसाइट, एक आंतरिक विंडोज फॉर्म एप्लिकेशन, और एक वायरलेस मोबाइल डिवाइस। सेवा का उद्देश्य दो गुना है: (1) केंद्रीय स्थान पर व्यावसायिक प्रक्रियाओं से संबंधित कोड को समेकित करने के लिए और (2) विरासत डेटाबेस तक पहुंच को लॉक करने के लिए, आखिरकार और एक बार और सभी सेवाओं के एक सूट के पीछे छिपाने के लिए।एएसपी.नेट वेब साइट + विंडोज फॉर्म ऐप + डब्ल्यूसीएफ सेवा: ग्राहक प्रमाण पत्र

वर्तमान में, तीनों अनुप्रयोगों में से प्रत्येक के पास एक ही डेटाबेस के थोड़ा अलग विचारों के साथ अपनी दृढ़ता और डोमेन परतें हैं। डेटाबेस से बात करने वाले सभी तीन अनुप्रयोगों के बजाय, वे डब्ल्यूसीएफ सेवा से बात करेंगे, कुछ ग्राहकों से नई सुविधाओं को सक्षम करेंगे (मोबाइल पिकर वर्तमान में ई-मेल भेजने के लिए प्रक्रियाओं को ट्रिगर नहीं कर सकता है) और अधिसूचना प्रणाली को केंद्रीकृत कर रहा है (इसके बजाय शेड्यूल किए गए कार्य नए ऑर्डर के लिए हर पांच मिनट में डेटाबेस को मतदान करते हैं, जब इन ग्राहकों में से किसी एक द्वारा AcceptNewOrder() सेवा विधि का आह्वान किया जाता है तो केवल ओवरहेड पेजिंग सिस्टम को पिंग करें)। सब कुछ, यह अब तक बहुत सचेत लगता है।

समग्र डिजाइन के मामले में, हालांकि, सुरक्षा की बात आने पर मैं स्टंप हो गया हूं। वर्तमान में विंडोज फॉर्म एप्लिकेशन विंडोज प्रिंसिपल का उपयोग करता है; कर्मचारी सक्रिय निर्देशिका में संग्रहीत होते हैं, और एप्लिकेशन स्टार्टअप पर, वे वर्तमान विंडोज उपयोगकर्ता के रूप में लॉगिन कर सकते हैं (जिस स्थिति में कोई पासवर्ड आवश्यक नहीं है) या वे अपना डोमेन नाम और पासवर्ड प्रदान कर सकते हैं। मोबाइल क्लाइंट में उपयोगकर्ता की कोई अवधारणा नहीं है; डेटाबेस से इसका कनेक्शन एक हार्डकोडेड स्ट्रिंग है। और वेबसाइट पर हजारों उपयोगकर्ता विरासत डेटाबेस में संग्रहीत हैं। तो मैं पहचान मॉडल को कैसे कार्यान्वित कर सकता हूं और इस से निपटने के लिए डब्ल्यूसीएफ एंडपॉइंट्स को कॉन्फ़िगर कर सकता हूं?

विंडोज फॉर्म एप्लिकेशन के संदर्भ में, यह कोई बड़ी समस्या नहीं है: डब्ल्यूसीएफ प्रॉक्सी को एक बार शुरू किया जा सकता है और स्मृति में चारों ओर लटका सकता है, इसलिए मुझे केवल क्लाइंट प्रमाण-पत्रों की आवश्यकता होती है (और प्रॉक्सी के लिए फिर से उनके लिए संकेत दे सकता है कभी दोष)। मोबाइल क्लाइंट सिर्फ विशेषीकृत किया जा सकता है और डब्ल्यूसीएफ सेवा के खिलाफ प्रमाणीकरण के लिए एक्स 50 9 प्रमाण पत्र का उपयोग कर सकता है। लेकिन मैं वेबसाइट के बारे में क्या करूँ?

वेबसाइट की स्थिति में, कुछ सेवाओं के लिए अनाम पहुंच की अनुमति है। और सेवाओं है कि काल्पनिक "ग्राहक" भूमिका में प्रमाणीकरण की आवश्यकता के लिए, मैं स्पष्ट रूप से नहीं दो कारणों के लिए प्रत्येक अनुरोध पर उन्हें प्रमाणित करने के लिए करना चाहते हैं:

  • मैं उनके यूज़रनेम और पासवर्ड हर बार की जरूरत है। जानकारी की इस जोड़ी को कहीं भी कहीं भी संग्रहीत करना - सत्र, एक एन्क्रिप्टेड कुकी, चंद्रमा - एक बुरा विचार की तरह लगता है।
  • मुझे प्रत्येक अनुरोध के लिए डेटाबेस में उपयोगकर्ता तालिका को हिट करना होगा। आउच।

एकमात्र समाधान जो मैं साथ आ सकता हूं वह है कि वेब साइट को एक विश्वसनीय उपप्रणाली के रूप में पेश किया जाए। डब्ल्यूसीएफ सेवा वेबसाइट से एक विशेष X509 प्रमाण पत्र की अपेक्षा करता है। वेब साइट, फॉर्म प्रमाणीकरण आंतरिक रूप से उपयोग कर रही है (जो एक बूलियन परिणाम लौटने वाली सेवा पर AuthenticateCustomer() विधि का आह्वान करती है), क्रेडेंशियल की सूची में अतिरिक्त दावा जोड़ सकती है, जैसे "[email protected] ग्राहक के रूप में लॉग इन है। " फिर किसी भी तरह से एक कस्टम IIdentity ऑब्जेक्ट और IPrincipal का निर्माण उस दावे के साथ सेवा पर किया जा सकता है, डब्ल्यूसीएफ सेवा को आश्वस्त किया जा रहा है कि वेबसाइट ने ग्राहक को सही तरीके से प्रमाणित किया है (यह पता चलेगा कि दावा कम से कम छेड़छाड़ नहीं हुआ है, क्योंकि यह समय से पहले वेब साइट का प्रमाण पत्र पता चलेगा)।

है, उन सभी के साथ

जगह में, WCF सेवा कोड [PrincipalPermission.Demand(Role=MyRoles.Customer)] या [PrincipalPermission.Demand(Role=MyRoles.Manager)], और Thread.CurrentPrincipal तरह बातें कहने के लिए कुछ है कि एक उपयोगकर्ता (एक ग्राहक या के लिए एक विशिष्ट नाम के लिए एक ई-मेल एड्रेस का प्रतिनिधित्व होता है में सक्षम हो जाएगा एक कर्मचारी, दोनों लॉगिंग और लेखा परीक्षा के लिए उपयोगी)।

दूसरे शब्दों में, प्रत्येक सेवा के लिए दो अलग-अलग अंत बिंदु मौजूद होंगे: जिसने प्रसिद्ध क्लाइंट X509 प्रमाणपत्र (मोबाइल डिवाइस और वेबसाइट के लिए) स्वीकार किया है, और जो Windows उपयोगकर्ताओं (कर्मचारियों के लिए) स्वीकार करता है।

क्षमा करें यह बहुत लंबा है। तो सवाल यह है: क्या इनमें से कोई भी समझ में आता है? प्रस्तावित समाधान समझ में आता है? और क्या मैं इसे बहुत जटिल बना रहा हूं?

उत्तर

15

ठीक है, मुझे लगता है कि मैं अपने प्रश्न पर एक स्टैब ले जाऊंगा कि मैंने विभिन्न दृष्टिकोणों के साथ कुछ घंटे बिताए हैं।

मेरा पहला दृष्टिकोण डब्ल्यूसीएफ सेवा और सार्वजनिक-सामना करने वाली वेबसाइट (वेब ​​साइट सेवा का उपभोक्ता/ग्राहक) के बीच प्रमाणपत्र-आधारित प्रमाणीकरण स्थापित करना था। makecert के साथ उत्पन्न कुछ परीक्षण गर्ट, उन्हें Personal, Trusted People, और Trusted Root Certification Authorities (क्योंकि मुझे हमारे डोमेन की प्रमाणपत्र सेवाओं के विरुद्ध वास्तविक उत्पन्न करने के लिए परेशान नहीं किया जा सकता), कुछ कॉन्फ़िगरेशन फ़ाइल संशोधनों और महान, हम सभी सेट हैं ।

वेबसाइट को उपयोगकर्ताओं के लिए उपयोगकर्ता नाम और पासवर्ड की जानकारी बनाए रखने से रोकने के लिए, विचार यह है कि एक बार जब उपयोगकर्ता फॉर्म प्रमाणीकरण के माध्यम से वेबसाइट पर लॉग इन हो जाता है, तो वेबसाइट केवल उपयोगकर्ता नाम (HttpContext.Current.User.Identity.Name के माध्यम से सुलभ) पास कर सकती है। X509CertificateSecurityToken के अतिरिक्त एक वैकल्पिक UserNameSecurityToken के रूप में जो वास्तव में संदेश को सुरक्षित करने के लिए उपयोग किया जाता है। यदि वैकल्पिक उपयोगकर्ता नाम सुरक्षा टोकन पाया जाता है, तो डब्ल्यूसीएफ सेवा कहती है "अरे, यह भरोसेमंद सबसिस्टम कहता है कि यह उपयोगकर्ता सही ढंग से प्रमाणीकृत है, इसलिए मुझे उस उपयोगकर्ता के लिए MyCustomPrincipal सेट अप करें और इसे वर्तमान थ्रेड पर इंस्टॉल करें ताकि वास्तविक सेवा कोड इसका निरीक्षण कर सकता है। " यदि यह नहीं था, तो MyCustomPrincipal का अज्ञात संस्करण स्थापित किया जाएगा।

तो मैं इसे लागू करने के लिए पांच घंटे तक चला गया, और variousblogs की सहायता से, मैं इसे करने में सक्षम था। (मैंने अपना अधिकांश समय एक समस्या को डीबग करने में बिताया, जहां मेरे पास प्रत्येक कॉन्फ़िगरेशन और सहायक वर्ग सही था, और उसके बाद के बाद मैंने अपना होस्ट शुरू किया, पहले नहीं, इसलिए मेरा कोई भी प्रयास वास्तव में प्रभावी नहीं हो रहा था। कुछ दिन मुझे कंप्यूटर से नफरत है।) मेरे पास TrustedSubsystemAuthorizationPolicy था जिसने X509 प्रमाण पत्र सत्यापन किया था, एक अज्ञात MyCustomPrincipal, TrustedSubsystemImpersonationAuthorizationPolicy स्थापित किया था, जो एक रिक्त पासवर्ड के साथ उपयोगकर्ता नाम टोकन स्वीकार कर लिया गया था और ग्राहक-भूमिका MyCustomPrincipal स्थापित किया था, यदि यह देखा गया कि अज्ञात विश्वसनीय उपप्रणाली प्रिंसिपल पहले से ही था स्थापित, और UserNameAuthorizationPolicy जो अन्य एंडपॉइंट्स के लिए नियमित उपयोगकर्ता नाम और पासवर्ड आधारित सत्यापन करता था जहां X509 प्रमाणपत्र का उपयोग नहीं किया जा रहा था। यह काम किया, और यह अद्भुत था।

लेकिन।

स्टैब-ई-इन-द-आई-बॉल पल आया जब मैं जेनरेट क्लाइंट प्रॉक्सी कोड के साथ झुका रहा था कि वेबसाइट इस सेवा से बात करने के लिए उपयोग करेगी। उत्पन्न ऑब्जेक्ट की ClientCredentials संपत्ति पर UserName निर्दिष्ट करना पर्याप्त था। लेकिन मुख्य समस्या यह है कि प्रमाण पत्र ChannelFactory के लिए विशिष्ट हैं, विशेष विधि आमंत्रण नहीं।

आप देखते हैं, नया() एक डब्ल्यूसीएफ क्लाइंट प्रॉक्सी को more expensiveyou might think से अधिक है। मैंने खुद को प्रदर्शन का परीक्षण करने के लिए एक त्वरित और गंदे ऐप लिखा: दोनों नए() एक नई प्रॉक्सी को जोड़ते हैं और दस बार एक विधि को कॉल करते हुए लगभग 6 सेकंड लगते हैं जबकि नया() एक प्रॉक्सी को एक बार जोड़ता है और केवल 10 बार लागत को कॉल करता है एक सेकंड के लगभग 3/5 वें। यह सिर्फ एक निराशाजनक प्रदर्शन अंतर है।

तो मैं क्लाइंट प्रॉक्सी के लिए सिर्फ पूल या कैश को कार्यान्वित कर सकता हूं, है ना?खैर, नहीं, यह आसानी से चारों ओर काम नहीं करता है: ग्राहक प्रमाण-पत्र जानकारी चैनल फैक्ट्री स्तर पर है क्योंकि इसका उपयोग परिवहन को सुरक्षित करने के लिए किया जा सकता है, केवल संदेश ही नहीं, और कुछ बाइंडिंग सेवा कॉल के बीच एक वास्तविक परिवहन खुला रखती हैं। चूंकि ग्राहक प्रमाण-पत्र प्रॉक्सी ऑब्जेक्ट के लिए अद्वितीय हैं, इसका मतलब है कि मुझे वर्तमान में वेबसाइट पर प्रत्येक उपयोगकर्ता के लिए एक अद्वितीय कैश किया गया उदाहरण होना होगा। यह संभावित रूप से बहुत सारी प्रॉक्सी ऑब्जेक्ट्स मेमोरी में बैठी है, और उस समस्या के करीब @ @ $ @ # है जो मैं पहली जगह से बचने की कोशिश कर रहा था! और चूंकि मुझे वैकल्पिक समर्थन उपयोगकर्ता नाम टोकन के लिए बाइंडिंग सेट करने के लिए Endpoint प्रॉपर्टी को स्पर्श करना है, इसलिए मैं automatic channel factory caching का लाभ नहीं ले सकता हूं जिसे माइक्रोसॉफ्ट ने .NET 3.5 में "मुफ्त में" जोड़ा है।

ड्राइंग बोर्ड पर वापस जाएं: मेरा दूसरा दृष्टिकोण, और मुझे लगता है कि मैं अब के लिए उपयोग कर रहा हूं, क्लाइंट वेब साइट और डब्ल्यूसीएफ सेवा के बीच X509 प्रमाणपत्र सुरक्षा के साथ रहना है। मैं अपने संदेशों में एक कस्टम "उपयोगकर्ता नाम" SOAP शीर्षलेख भेजूंगा, और डब्ल्यूसीएफ सेवा उस एसओएपी हेडर का निरीक्षण कर सकती है, यह निर्धारित कर सकती है कि यह एक विश्वसनीय उपप्रणाली जैसे वेब साइट से आया है, और यदि ऐसा है, तो MyCustomPrincipal को इसी तरह से इंस्टॉल करें पहले की तरह तरीके।

Codeproject और random people on Google अद्भुत चीजें हैं क्योंकि उन्होंने running into a weird WCF bug when it comes to custom endpoint behaviors in configuration के बाद भी इसे पाने और जल्दी से चलाने में मेरी सहायता की। क्लाइंट साइड और सेवा पक्ष पर संदेश निरीक्षकों को कार्यान्वित करके - उपयोगकर्ता नाम शीर्षलेख जोड़ने के लिए, और इसे पढ़ने और सही प्रिंसिपल इंस्टॉल करने के लिए - यह कोड एक ही स्थान पर है जहां मैं बस इसके बारे में भूल सकता हूं। चूंकि मुझे Endpoint संपत्ति को छूने की ज़रूरत नहीं है, इसलिए मुझे अंतर्निहित चैनल फ़ैक्टरी कैशिंग मुफ्त में मिलती है। और चूंकि ClientCredentials किसी भी उपयोगकर्ता को वेब साइट तक पहुंचने के लिए समान है (वास्तव में, वे हमेशा X509 प्रमाणपत्र होते हैं - केवल संदेश के भीतर उपयोगकर्ता नाम शीर्षलेख का मान बदलता है), क्लाइंट प्रॉक्सी कैशिंग या प्रॉक्सी पूल जोड़ना बहुत अधिक है तुच्छ।

तो मैं यही कर रहा हूं। WCF सेवा में वास्तविक सेवा कोड जैसे काम कर सकें


    // Scenario 1: X509Cert + custom UserName header yields for a Web site customer ... 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out, say, "[email protected]" 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Customer)); // prints out "True" 

    // Scenario 2: My custom UserNameSecurityToken authentication yields for an employee ... 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out, say, CN=Nick,DC=example, DC=com 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Employee)); // prints out "True" 

    // Scenario 3: Web site doesn't pass in a UserName header ... 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.Identity.Name); // prints out nothing 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Guest)); // prints out "True" 
    Console.WriteLine("{0}", Thread.CurrentPrincipal.IsInRole(MyRoles.Customer)); // prints out "False" 

यह कोई फर्क नहीं पड़ता कि कैसे इन लोगों को प्रमाणीकृत किया गया, या कुछ है कि SQL सर्वर में रह रहे हैं या कुछ सक्रिय निर्देशिका में रह रहे हैं: के लिए PrincipalPermission.Demand और प्रवेश ऑडिटिंग उद्देश्यों अब एक तस्वीर है।

मुझे आशा है कि इससे भविष्य में कुछ गरीब आत्मा की मदद मिलेगी।

+0

खुशी है कि आप अपने आप को हल कर ली, मेरी समस्या थोड़ी अलग है, लेकिन मैं खर्च करने का डब्ल्यूएस/डब्ल्यूसीएफ-सुरक्षा पर अपने बालों को फाड़ने के लगभग 5 घंटे। आह। – GONeale

+0

यदि आपको लगता है कि आप मेरी विशेष समस्या पर प्रकाश डाल सकते हैं (डब्ल्यूसीएफ सुरक्षा और लंबी पोस्ट के साथ क्या है? कृपया) - http://stackoverflow.com/questions/395892/userpass- प्रमाणीकरण-using-restful-wcf- विंडोज़ फॉर्म ग्राहम – GONeale

+1

मुझे बहुत दर्द होता है लेकिन मूल रूप से इसके साथ समाप्त हो गया है, पोस्ट के लिए धन्यवाद ... – AJM

0

anonymouse सार्वजनिक उपयोग उपयोग basichttpbinding के लिए है और यह भी web.config फ़ाइल में निम्न है

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