2010-05-12 6 views
8

से डोमेन SQL सर्वर 2005 से कनेक्ट करें, मैंने कुछ दिन पहले (Access to SQL Server 2005 from a non-domain machine using Windows authentication) एक प्रश्न पूछा था, जिसमें कुछ दिलचस्प, लेकिन उपयोग करने योग्य सुझाव नहीं थे। मैं फिर से सवाल पूछना चाहता हूं, लेकिन स्पष्ट करें कि मेरी बाधाएं क्या हैं:गैर-डोमेन मशीन

मेरे पास एक विंडोज डोमेन है जिसके अंतर्गत एक मशीन SQL Server 2005 चला रही है और जिसे केवल Windows प्रमाणीकरण का समर्थन करने के लिए कॉन्फ़िगर किया गया है। मैं एक ही नेटवर्क पर एक मशीन पर एक सी # क्लाइंट एप्लिकेशन चलाने के लिए चाहता हूं, लेकिन जो डोमेन पर नहीं है, और SQL Server 2005 इंस्टेंस पर डेटाबेस तक पहुंच है।

मैं मशीन पर ओएस या एसक्यूएल सर्वर उपयोगकर्ताओं को बना या संशोधित नहीं कर सकता, और मैं अनुमतियों या प्रतिरूपण में कोई बदलाव नहीं कर सकता, और मैं रनस का उपयोग नहीं कर सकता।

मुझे पता है कि मैं पर्ल और जावा एप्लिकेशन लिख सकता हूं जो केवल इन चार पैरामीटर का उपयोग कर SQL सर्वर डेटाबेस से कनेक्ट हो सकते हैं: सर्वर का नाम, डेटाबेस नाम, उपयोगकर्ता नाम (फॉर्म डोमेन \ उपयोगकर्ता में), और पासवर्ड।

सी # में मैं भर के विभिन्न चीजों की कोशिश की है:

string connectionString = "Data Source=server;Initial Catalog=database;User Id=domain\user;Password=password"; 
SqlConnection connection = new SqlConnection(connectionString); 
connection.Open(); 

और सच्चे और झूठे के लिए एकीकृत सुरक्षा स्थापित करने की कोशिश की, लेकिन कुछ भी काम करने के लिए लगता है। क्या मैं सी # में बस असंभव करने की कोशिश कर रहा हूं?

किसी भी मदद के लिए धन्यवाद, मार्टिन

उत्तर

2

जैसा कि आप सही ढंग से कहते हैं, एक लिनक्स मशीन पर जेडीबीसी या पर्ल दोनों SQL प्रमाणीकरण और वर्तमान में लॉग ऑन उपयोगकर्ता से भिन्न प्रमाणपत्रों का उपयोग कर SQL सर्वर से कनेक्ट हो सकते हैं। रास्ते में The same is true for Windows CE devices

मुझे लगता है कि यह है कि यह सी # लेकिन SQL सर्वर ओएलई डीबी ड्राइवर का मुद्दा नहीं है। मुझे लगता है कि उपरोक्त वर्णित विधियों को नेटवर्क स्तर पर "कुछ विशिष्ट प्रमाण-पत्रों का उपयोग करके विंडोज मशीन होने का नाटक करना"; एक सुविधा, जो SQL सर्वर ओएलई डीबी ड्राइवर की कमी है। इस प्रकार, मेरा सुझाव एक वैकल्पिक (शायद वाणिज्यिक?) ओएलई डीबी ड्राइवर की तलाश करना होगा जो SQL सर्वर डेटाबेस तक पहुंच सकता है। मुझे यकीन नहीं है कि ऐसी चीज मौजूद है या नहीं।

2

आप उपयोगकर्ता नाम और पासवर्ड का उपयोग कर एसक्यूएल सर्वर प्रमाणीकरण, अर्थात प्रमाणीकरण अनुमति देने के लिए configure SQL Server किया है।

आप डोमेन उपयोगकर्ता नाम/पासवर्ड 'जैसे' सर्वर प्रमाणीकरण द्वारा प्रमाणीकृत नहीं कर सकते हैं, यानी डोमेन उपयोगकर्ता नाम/पासवर्ड सीधे निर्दिष्ट करें।

मैं निश्चित रूप से गलत हो सकता हूं, लेकिन मुझे यकीन है कि यह सी # या .NET की समस्या नहीं है। आप अपने पर्ल या जावा एप्लिकेशन में SQL सर्वर पर कैसे लॉगिन कर सकते हैं ??

+0

असल में, सवाल स्पष्ट रूप से बताता है कि SQL सर्वर प्रमाणीकरण का उपयोग एक विकल्प नहीं है (कोई डाउनवोट नहीं है, हालांकि ...) – Heinzi

4

कनेक्शन स्ट्रिंग में उपयोगकर्ता नाम और पासवर्ड निर्दिष्ट करने के लिए बेकार है क्योंकि वे SQL प्रमाणीकरण का संकेत देते हैं, और आपने पहले ही निर्दिष्ट किया है कि SQL सर्वर केवल Windows प्रमाणीकरण स्वीकार करता है।

यदि सर्वर SQL प्रमाणीकरण की अनुमति नहीं देता है तो केवल कनेक्ट करने की संभावना Windows प्रमाणीकरण का उपयोग करना है, यानी। IntegratedSecurity=true। जिसका अर्थ यह है कि आपका क्लाइंट प्रमाणित करेगा क्योंकि जो भी क्रेडेंशियल प्रक्रिया चला रहा है (या वर्तमान में प्रतिरूपित किया जा रहा है)।

  • जुड़ें गैर-डोमेन एक डोमेन में मशीन में शामिल हो गए (! यह अपने आप डोमेन हो सकता है) सर्वर पर भरोसा करता है:

    आदेश में Windows प्रमाणीकरण काम करने के लिए, आप निम्न में से एक का चयन करने के लिए है डोमेन, फिर क्लाइंट प्रक्रिया को डोमेन \ उपयोगकर्ता प्रमाण-पत्र के रूप में चलाएं।

  • एनटीएलएम दर्पण खातों का उपयोग करें: क्लाइंट पर स्थानीय उपयोगकर्ताओं की एक जोड़ी और समान नाम और पासवर्ड वाले सर्वर।
  • SQL सर्वर पर ANONYMOUS पहुंच के रूप में अनुदान।

आप ग्राहक मेजबान विश्वास सर्वर डोमेन नहीं कर सकते हैं, और न ही आप NTLM जोड़ सकते हैं नजर आता खातों, और एसक्यूएल सर्वर व्यवस्थापक समझदार पर्याप्त बेनामी सक्षम करने के लिए तो आप कनेक्ट करने के लिए सक्षम नहीं होगा नहीं है।

+1

कोई डाउनवोट नहीं है लेकिन: प्रश्न SQL सर्वर एक्सेस विधियों के परिचय के लिए नहीं पूछा गया था। यह पूछा गया कि .NET Framework Windows प्रमाणीकरण और वैकल्पिक क्रेडेंशियल्स का उपयोग करते हुए SQL सर्वर से कनेक्ट करने में सक्षम नहीं है * हालांकि * अन्य क्लाइंट टेक्नोलॉजीज (नीचे उल्लिखित जेडीबीसी ड्राइवर, पर्ल एसक्यूएल सर्वर ड्राइवर, सिस्टम सीटा विंडोज़ सीईसी क्लाइंट। ..) आपको ऐसी चीज करने की अनुमति देता है (इसलिए यह SQL सर्वर की सीमा नहीं हो सकता है)। – Heinzi

+0

@ हिनजी रीमस वर्तमान में प्रतिरूपित होने वाले प्रमाण-पत्रों का उल्लेख करता है। यह संभव है कि चालक बस ऐसा करते हैं। –

0

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

रीमस के सुझावों का उत्तर देने के लिए, मैं उन तीनों चीजों में से कोई भी नहीं कर सकता जो उन्होंने सुझाए हैं और फिर भी जावा और पर्ल अनुप्रयोग कनेक्ट करने में सक्षम हैं। कोई अन्य विचार?

धन्यवाद, मार्टिन

0

यह prompt for credentials के लिए एक विकल्प है?

+0

नहीं - कम से कम जिस तरह से मुझे लगता है कि आपका मतलब है। कनेक्शन क्रेडेंशियल कॉन्फ़िगरेशन फ़ाइल में निर्दिष्ट होते हैं जो C# अनुप्रयोग प्रारंभ होने पर पढ़ता है। – user304582

0

यहाँ नमूना कोड है कि मैं jTDS JDBC ड्राइवर का उपयोग कर एक गैर-डोमेन मशीन से कनेक्ट करने के लिए उपयोग करते हैं:।

Class.forName ("net.sourceforge.jtds.jdbc.Driver") newInstance() ; स्ट्रिंग url = "jdbc: jtds: sqlserver: // server/डेटाबेस; डोमेन = डोमेन"; conn = DriverManager.getConnection (url, "user", "password");

+0

आपको इन प्रश्नों को अपने प्रश्न में जोड़ना चाहिए (इसे अपने प्रश्न के नीचे "संपादन" बटन का उपयोग करें) इसे उत्तर के रूप में जोड़ने के बजाय। – Heinzi

8

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

बात है मुझे पता था कि मैं इसे किसी तरह runas का उपयोग कर में काम मिल सकता है क्योंकि मैं इसे SSMS साथ साबित होता:

C:\WINDOWS\system32\runas.exe /netonly /savecred /user:megacorp\joe.bloggs "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\SqlWb.exe" 

/netonly झंडा मुझे स्थानीय पहचान के साथ exe निष्पादित करने के लिए अनुमति दी और रिमोट क्रेडेंशियल्स के साथ नेटवर्क तक पहुंचें, मुझे लगता है, वैसे भी मुझे रिमोट सर्वर से अपेक्षित परिणाम सेट मिला है। समस्या रनस कमांड ने एप्लिकेशन को डीबग करना बहुत मुश्किल बना दिया, और यह अच्छा गंध नहीं हुआ।

 
    using System; 
    using System.Runtime.InteropServices; // DllImport 
    using System.Security.Principal; // WindowsImpersonationContext 

    namespace TestApp 
    { 
     class Impersonator 
     { 
      // group type enum 
      enum SECURITY_IMPERSONATION_LEVEL : int 
      { 
       SecurityAnonymous = 0, 
       SecurityIdentification = 1, 
       SecurityImpersonation = 2, 
       SecurityDelegation = 3 
      } 

      // obtains user token 
      [DllImport("advapi32.dll", SetLastError = true)] 
      static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, 
       int dwLogonType, int dwLogonProvider, ref IntPtr phToken); 

      // closes open handes returned by LogonUser 
      [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
      extern static bool CloseHandle(IntPtr handle); 

      // creates duplicate token handle 
      [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
      extern static bool DuplicateToken(IntPtr ExistingTokenHandle, 
       int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); 

      WindowsImpersonationContext newUser; 

      /// 
      /// Attempts to impersonate a user. If successful, returns 
      /// a WindowsImpersonationContext of the new users identity. 
      /// 
      /// Username you want to impersonate 
      /// Logon domain 
      /// User's password to logon with 
      /// 
      public Impersonator(string sUsername, string sDomain, string sPassword) 
      { 
       // initialize tokens 
       IntPtr pExistingTokenHandle = new IntPtr(0); 
       IntPtr pDuplicateTokenHandle = new IntPtr(0); 
       pExistingTokenHandle = IntPtr.Zero; 
       pDuplicateTokenHandle = IntPtr.Zero; 

       // if domain name was blank, assume local machine 
       if (sDomain == "") 
        sDomain = System.Environment.MachineName; 

       try 
       { 
        const int LOGON32_PROVIDER_DEFAULT = 0; 

        // create token 
        // const int LOGON32_LOGON_INTERACTIVE = 2; 
        const int LOGON32_LOGON_NEW_CREDENTIALS = 9; 
        //const int SecurityImpersonation = 2; 

        // get handle to token 
        bool bImpersonated = LogonUser(sUsername, sDomain, sPassword, 
         LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle); 

        // did impersonation fail? 
        if (false == bImpersonated) 
        { 
         int nErrorCode = Marshal.GetLastWin32Error(); 

         // show the reason why LogonUser failed 
         throw new ApplicationException("LogonUser() failed with error code: " + nErrorCode); 
        } 

        bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle); 

        // did DuplicateToken fail? 
        if (false == bRetVal) 
        { 
         int nErrorCode = Marshal.GetLastWin32Error(); 
         CloseHandle(pExistingTokenHandle); // close existing handle 

         // show the reason why DuplicateToken failed 
         throw new ApplicationException("DuplicateToken() failed with error code: " + nErrorCode); 
        } 
        else 
        { 
         // create new identity using new primary token 
         WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle); 
         WindowsImpersonationContext impersonatedUser = newId.Impersonate(); 

         newUser = impersonatedUser; 
        } 
       } 
       finally 
       { 
        // close handle(s) 
        if (pExistingTokenHandle != IntPtr.Zero) 
         CloseHandle(pExistingTokenHandle); 
        if (pDuplicateTokenHandle != IntPtr.Zero) 
         CloseHandle(pDuplicateTokenHandle); 
       } 
      } 

      public void Undo() 
      { 
       newUser.Undo(); 
      } 
     } 
    } 

यह सिर्फ उपयोग करने के लिए:

Impersonator impersonator = new Impersonator("username", "domain", "password"); 

//Connect to and use SQL server 

impersonator.Undo(); 

अंततः मैं the code project जो सक्रिय निर्देशिका में हेरफेर करने के सत्यापन के बारे में बात कर रहा था पर इस लेख पाया, यहां मुख्य वर्ग है कि प्रतिरूपण करता है मैंने पूर्ववत विधि में जोड़ा है अन्यथा प्रतिरूपण वस्तु एकत्रित कचरा पाने के लिए प्रतिबद्ध है। मैंने LOGON32_LOGON_NEW_CREDENTIALS का उपयोग करने के लिए कोड भी बदल दिया लेकिन यह एक पोक था और इसे काम करने के लिए चला गया; मुझे अभी भी पूरी तरह से समझने की जरूरत है कि यह क्या करता है, मुझे लगता है कि यह रनस पर/नेटोनली ध्वज जैसा ही है। मैं कन्स्ट्रक्टर को थोड़ा तोड़ने जा रहा हूं।

+0

+1, अच्छा समाधान। कचरा संग्रहण समस्या के बारे में: आप अपनी कक्षा का नाम 'प्रतिरूपण कॉन्टेक्स्ट' में बदल सकते हैं, 'आईडीस्पोजेबल' का उत्तराधिकारी कर सकते हैं और 'निपटान' में 'पूर्ववत करें 'सामग्री कर सकते हैं। इस प्रकार, आपकी कक्षा का उपयोग इस प्रकार किया जा सकता है: 'नए प्रतिरूपण कोटेक्स्ट (...) {...} 'का उपयोग करना। इससे यह भी सुनिश्चित होगा कि आप प्रतिरूपण पूर्ववत करने के लिए "भूल" नहीं सकते। – Heinzi