2011-05-25 14 views
13

मेरे पास एक डीसीओएम क्लाइंट और सर्वर अनुप्रयोग हैं जो ओएलई ऑटोमेशन मार्शलर का उपयोग करते हैं। वे एक ही पीसी पर चलते समय ठीक काम करते हैं, लेकिन जब सर्वर एक अलग पीसी पर होता है तो उसी डोमेन में नहीं, मुझे E_ACCESSDENIED (0x80070005) मिलता है।डीसीओएम में प्रतिरूपण कैसे काम करता है?

सर्वर पीसी किसी भी DCOM ऑब्जेक्ट को उस उपयोगकर्ता को लॉगिन करने के लिए dcomcnfg के साथ कॉन्फ़िगर किया गया है जिसका ग्राहक और लॉगिन मैं क्लाइंट पर निर्दिष्ट करता हूं। सर्वर ऐप और इसकी टाइप लाइब्रेरी सर्वर पीसी पर पंजीकृत हैं।

टाइप लाइब्रेरी क्लाइंट पीसी पर भी पंजीकृत है। मैं सीधे क्लाइंट ऐप में सर्वर का नाम निर्दिष्ट करता हूं, इसलिए क्लाइंट पीसी पर जहां तक ​​मैं समझता हूं, वहां कोई dcomcnfg कॉन्फ़िगरेशन आवश्यक नहीं है।

सर्वर नाम, लॉगिन, डोमेन और पासवर्ड के साथ CreateInstanceEx() ठीक काम करता है। यह IU अज्ञात लौटाता है और साथ ही सर्वर पीसी पर सर्वर ऐप शुरू करता है।

लेकिन जब मैं सर्वर का समर्थन करने वाले इंटरफ़ेस के लिए QueryInterface() का प्रयास करता हूं, तो मुझे E_ACCESSDENIED मिलता है।

पहले, जिसका क्रेडेंशियल्स मैं ClientApp में निर्दिष्ट उपयोगकर्ता द्वारा एक सफल नेटवर्क लॉगिन:

का विश्लेषण सुरक्षा ईवेंट लॉग, मैं वहाँ दो रिकॉर्ड है। यह तब होता है जब मैं CreateInstanceEx() को कॉल करता हूं।

अगला, द्वारा एक असफल लॉगिन प्रयास जिसके तहत मैं क्लाइंट पीसी पर लॉग इन हूं। चूंकि दो पीसी डोमेन में नहीं हैं, इसलिए यह उपयोगकर्ता सर्वर पीसी के लिए अज्ञात है।

अब, यह उपयोगकर्ता सर्वर में लॉग इन क्यों करेगा, खासकर जब मैं सभी चीजों के QueryInterface को कॉल करता हूं?

CreateInterfaceEx पैराम का अध्ययन, ऐसा प्रतीत होता है कि किसी तरह का प्रतिरूपण तंत्र चल रहा है। लेकिन यह अस्पष्ट है जो कौन प्रतिरूपण करता है।

  1. उपयोगकर्ता जिसके तहत ServerApp सर्वर पीसी पर चलाता है (: Dcomcnfg में विन्यस्त के रूप में): वहाँ तीन उपयोगकर्ता शामिल साख है।

  2. उपयोगकर्ता जिसका क्रेडेंशियल क्लाइंट ऐप कनेक्ट करते समय निर्दिष्ट करता है।

  3. उपयोगकर्ता जिसके क्रेडेंशियल्स क्लाइंटएप क्लाइंट पीसी पर चलता है।

कोई फर्क नहीं पड़ता कि आप इसे कैसे देखते हैं, यदि # 3 शामिल है तो यह एक उपयोगकर्ता बहुत अधिक है। यदि डीसीओएम सर्वर पीसी पर # 3 की पहचान/प्रतिरूपण करने जा रहा है, तो मुझे # 2 के क्रेडेंशियल निर्दिष्ट करने की आवश्यकता क्यों है? किस बिंदु पर?

डीसीओएम के लिए # 2 का प्रतिरूपण करना तर्कसंगत प्रतीत होता क्योंकि यह मैंने अपने प्रमाण-पत्र के रूप में स्पष्ट रूप से निर्दिष्ट किया है। लेकिन फिर दूसरा लॉगिन प्रयास क्यों?

क्या कोई यह बता सकता है कि प्रतिरूपण वास्तव में कैसे काम करता है, और अगर इसे अनदेखा करने और dcomcnfg में निर्दिष्ट उपयोगकर्ता के रूप में चलाने का कोई तरीका है तो भी?

उत्तर

12

मेरे अपने प्रश्न का उत्तर दें।ज्यादा अन्वेषण के बाद यह स्पष्ट हो गया है कि DCOM दो अलग पहचान मामलों है: ऑब्जेक्ट निर्माण (CoCreateInstanceEx) विधि कॉल के लिए

  • प्राधिकरण के लिए

    1. प्राधिकरण।

    अज्ञात कारणों से, # 2 # 1 सेटिंग्स का उत्तराधिकारी नहीं है। डिफ़ॉल्ट रूप से यह क्लाइंट प्रक्रिया के प्रमाण-पत्रों का उपयोग करता है, इसलिए अजीब लॉगिन।

    # 2 के लिए प्रमाण-पत्र निर्दिष्ट करने के दो तरीके हैं। पहला एक CoSetProxyBlanket है। यह केवल एक निर्दिष्ट प्रॉक्सी (marshaller-unmarshaller) के लिए क्रेडेंशियल सेट:

    CoCreateInstanceEx(IID_IObject1, /*login, pass*/, obj1); //Success! 
    //Logged in and recevied IObject1 proxy in obj1 
    
    obj1->DoSomething(); 
    //IObject1 proxy in obj1 now tries to login under process credentials. 
    //Failure! E_ACCESSDENIED 
    
    CoSetProxyBlanket(obj1, /*login, pass*/); //Success! 
    //IObject1 proxy is now authorized. 
    
    obj1->DoSomething(); //Success! 
    obj1->QueryInterface(IID_IObject2, obj2); //Success! 
    
    obj2->DoSomethingElse(); //Failure! 
    //This different proxy for IObject2 have not yet been authorized. 
    
    CoSetProxyBlanket(obj2, /*login, pass*/); 
    //etc. 
    

    यह ध्यान रखें कि जबकि CoCreateInstanceEx प्रतिरूपण स्तर की आवश्यकता है कम से कम का रूप धारण करने के लिए, CoSetProxyBlanket की पहचान के अलावा कुछ पर काम नहीं लगता है महत्वपूर्ण है।

    एक और विकल्प पूरे प्रक्रिया के लिए डिफ़ॉल्ट प्रमाण-पत्र सेट करने के लिए CoInitializeSecurity का उपयोग करना है। तो फिर तुम हर प्रॉक्सी पर CoSetProxyBlanket कॉल करने के लिए की जरूरत नहीं है:

    CoInitializeSecurity(/* login, pass */); 
    CoCreateInstanceEx(IID_IUnknown, /*login, pass*/, obj); //Success! 
    obj->DoSomething(); //Success! 
    

    ग्राहक आप पर CoInitializeSecurity का उपयोग करते समय asAuthSvc भी निर्दिष्ट करने, भले ही MSDN तुम नहीं कहते हैं।

    इस विधि की कमी स्पष्ट रूप से है कि यदि आपके पास विभिन्न पीसी से कई डीसीओएम ऑब्जेक्ट्स हैं तो आपको इस कॉल में सभी क्रेडेंशियल्स निर्दिष्ट करना होगा और संभवतः हर बार जब आप खुले रहते हैं तो हर कंप्यूटर के खिलाफ कोशिश की जा रही है एक अलग प्रॉक्सी।

    यह भी विश्वसनीय नहीं है जब आप एक डीएलएल से चल रहे हैं (क्या होगा यदि किसी प्रक्रिया में अलग-अलग डिफ़ॉल्ट सुरक्षा है?)। तो, प्रत्येक कॉल से लौटने से पहले CoSetsProxyBlanket को QueryInterface wrapper को लागू करना शायद बेहतर होगा।

  • 0

    डेल्फी में काम करने वाले लोगों के लिए एक छोटा सा नोट है जो आपका बहुत समय बचा सकता है। obj as ISomeInterface ऑपरेशन करने के बाद, आपको नए उदाहरण के लिए CoSetProxyBlanket पर कॉल करना होगा। यह बहुत स्पष्ट नहीं हो सकता है, लेकिन हम सभी जानते हैं कि as ऑपरेटर QueryInterface विधि कॉल करता है, और यह नया उदाहरण वापस कर सकता है।

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