2016-11-28 4 views
13

मैं एक आंतरिक उपयोग अनुप्रयोग बनाने के साथ शामिल हूं जिसके माध्यम से उपयोगकर्ता Google ड्राइव के भीतर संग्रहीत करने के लिए फ़ाइलों को अपलोड कर सकते हैं। चूंकि यह अनुशंसा की जाती है कि सेवा मालिकों के रूप में सेवा खातों का उपयोग न करें, मैं एक निर्दिष्ट उपयोगकर्ता खाते की ओर से आवेदन अपलोड करना चाहता था, जिस पर कंपनी sysadmin पहुंच है।किसी सेवा खाते में Google ड्राइव पहुंच के प्रतिनिधिमंडल की विफलता

मैंने सेवा खाते के साथ-साथ एप्लिकेशन बनाया है। वहाँ सेवा खाते के लिए बनाई गई दो चाबियाँ, कर रहे हैं के रूप में मैं कोशिश की है दोनों JSON और PKCS12 प्रारूपों इस लक्ष्य को हासिल करने की कोशिश कर:

API Manager Credentials page

मैं OAuth 2.0 क्लाइंट आईडी विवरण डाउनलोड किया है, और यह भी .json है सेवा खाते चाबी के लिए और .p12 फ़ाइलें (इसी क्रम में के रूप में ऊपर प्रदर्शित):

Downloaded files for client and service accounts

मैं था मेरे सिस्टम प्रशासक सेवा खाते में ड्राइव API पहुंच के लिए प्राधिकरण को सौंपने के लिए यहाँ विस्तृत चरणों को देखें: https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account

हमने पाया कि चरण 4 में "क्लाइंट नाम" के लिए काम करने वाली एकमात्र चीज वेब एप्लिकेशन (समापन .apps.googleusercontent.com) के लिए सूचीबद्ध "क्लाइंट आईडी" थी। लंबे हेक्साडेसिमल सेवा खाते चाबी के लिए सूचीबद्ध आईडी नहीं थे कि यह क्या आवश्यक (देखें नीचे): उपरोक्त के पहले

Authorized API client access

, मुझे लगता है कि सीधे सेवा को अपलोड कर सकते हैं कोड है जो एक DriveService उदाहरण बनाने होता था खाते, सेवा खाता चाबी के लिए .json फ़ाइल को संदर्भित:

private DriveService GetServiceA() 
{ 
    var settings = SettingsProvider.GetInstance(); 

    string keyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.json"); 
    var scopes = new string[] { DriveService.Scope.Drive }; 

    var stream = new IO.FileStream(keyFilePath, IO.FileMode.Open, IO.FileAccess.Read); 
    var credential = GoogleCredential.FromStream(stream); 
    credential = credential.CreateScoped(scopes); 

    var service = new DriveService(new BaseClientService.Initializer() 
    { 
     HttpClientInitializer = credential, 
     ApplicationName = "MyAppName" 
    }); 

    return service; 
} 

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

एक बार जब प्रतिनिधिमंडल स्पष्ट रूप से क्रमबद्ध किया गया था, तो मैंने ऊपर दिए गए प्रतिनिधिमंडल संदर्भ में दिखाए गए कोड को अनुकूलित करने का प्रयास किया, जो .json कुंजी फ़ाइल से आवश्यक विवरण निकालने के लिए कहीं और से कोड के संयोजन के साथ संयोजन किया गया।

अपवाद विवरण::

FileList fileList = service.FileList().Execute(); 

मैं एक त्रुटि प्राप्त: इस कोड के साथ, जैसे ही मैं किसी भी एपीआई आदेश, यहां तक ​​कि के रूप में सरल निष्पादित करने के लिए के रूप में की कोशिश के रूप में Google.Apis.Auth.OAuth2.Responses.TokenResponseException : त्रुटि: "unauthorized_client", विवरण: "अनधिकृत ग्राहक या अनुरोध में गुंजाइश है।", उरी: ""

कि प्रयास के लिए कोड है:

private DriveService GetServiceB() 
{ 
    var settings = SettingsProvider.GetInstance(); 

    string keyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.json"); 
    string serviceAccountEmail = "<account-email>@<project-id>.iam.gserviceaccount.com"; 
    var scopes = new string[] { DriveService.Scope.Drive }; 

    var stream = new IO.FileStream(keyFilePath, IO.FileMode.Open, IO.FileAccess.Read); 
    var reader = new IO.StreamReader(stream); 
    string jsonCreds = reader.ReadToEnd(); 
    var o = JObject.Parse(jsonCreds); 
    string privateKey = o["private_key"].ToString(); 

    var credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(serviceAccountEmail) 
    { 
     Scopes = scopes, 
     User = "[email protected]" 
    } 
    .FromPrivateKey(privateKey) 
); 

    var service = new DriveService(new BaseClientService.Initializer() 
    { 
    HttpClientInitializer = credential, 
    ApplicationName = "MyAppName" 
    }); 

    return service; 
} 

अंत में, मैं दूसरे से बनाया एक बचाने के लिए rvice खाता कुंजी।आदेश और अधिक बारीकी से अधिकार प्रतिनिधिमंडल दस्तावेज में कोड से मिलान करने में p12 फ़ाइल है, लेकिन जो एक ही अपवाद में परिणाम:

private DriveService GetServiceC() 
{ 
    var settings = SettingsProvider.GetInstance(); 

    string p12KeyFilePath = HostingEnvironment.MapPath("~/App_Data/keyfile.p12"); 
    string serviceAccountEmail = "<account-email>@<project-id>.iam.gserviceaccount.com"; 
    var scopes = new string[] { DriveService.Scope.Drive }; // Full access 

    X509Certificate2 certificate = new X509Certificate2(
    p12KeyFilePath, 
    "notasecret", 
    X509KeyStorageFlags.Exportable 
); 

    var credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(serviceAccountEmail) 
    { 
     Scopes = scopes, 
     User = "[email protected]" 
    } 
    .FromCertificate(certificate) 
); 

    var service = new DriveService(new BaseClientService.Initializer() 
    { 
    HttpClientInitializer = credential, 
    ApplicationName = "MyAppName" 
    }); 

    return service; 
} 

minimial प्रासंगिक वर्ग जहां इस पद्धति रहती है:

public class GoogleDrive 
{ 
    public DriveService Service { get; private set; } 

    public GoogleDrive() 
    { 
    this.Service = this.GetService(); 
    } 

    private DriveService GetService() 
    { 
    // Code from either A, B or C 
    } 

    public FilesResource.ListRequest FileList() 
    { 
    return this.Service.Files.List(); 
    } 
} 

और वह है इस फैशन में प्रयोग किया जाता है:

var service = new GoogleDrive(); 
FilesResource.ListRequest listRequest = service.FileList(); 
FileList fileList = listRequest.Execute(); 

उस अंतिम पंक्ति पर अपवाद होता है।

मुझे समझ में नहीं आता कि मेरा सेवा खाता नामित उपयोगकर्ता की तरफ से क्यों कार्य नहीं कर सकता है, जो उस डोमेन का हिस्सा है जिसके लिए आवेदन के सेवा खाते को प्राधिकृत प्राधिकारी होना चाहिए। यह क्या है कि मैंने यहां गलत समझा है?

var credential = new ServiceAccountCredential... 

होना चाहिए

ServiceAccountCredential credential = new ServiceAccountCredential... 

बी की जांच:

+0

यह कॉन्फ़िगरेशन त्रुटि का विषय हो सकता है। क्या आपने क्लाइंट नाम में सेवा खाता क्लाइंट आईडी दर्ज की है? यह [आपके सेवा खाते में प्रतिनिधि डोमेन-व्यापी प्राधिकरण] में चरण # 5 है (https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account) – noogui

+0

@noogui द जेसन फ़ाइल जेनरेट की गई सेवा खाता कुंजी में "client_id" प्रविष्टि होती है, जो 21 अंकों का दशमलव संख्या है। चरण # 5 के लिए इसका उपयोग एक त्रुटि संदेश दिखाता है: "यह क्लाइंट नाम अभी तक Google के साथ पंजीकृत नहीं है।" –

उत्तर

6

मुझे जवाब मिला है, और यह कॉन्फ़िगरेशन था, कोड नहीं। प्राधिकरण के प्रतिनिधिमंडल के लिए कदमों के साथ साझा किए गए लिंक में सेवा खाते में बनाने का विकल्प उपलब्ध नहीं है: एक चेकबॉक्स यह कहता है कि खाता डोमेन-व्यापी प्रतिनिधिमंडल (डीडब्ल्यूडी) के लिए योग्य होगा।

यह लिंक सेवा खाता निर्माण और प्रतिनिधिमंडल और अधिक सही वर्णन करता है: https://developers.google.com/identity/protocols/OAuth2ServiceAccount

मैं जब मैं सेवा खाता नहीं बनाया है DWD के बारे में पता नहीं था, और इसलिए मैं उस विकल्प को नहीं चुना था। इसे चुनने के लिए वापस जाना और एक सेवा खाता संपादित करना संभव है। एक बार ऐसा करने के बाद, मैं व्यवस्थापक कंसोल के "एपीआई क्लाइंट एक्सेस प्रबंधित करें" भाग में उपयोग के लिए एक सही क्लाइंट आईडी पुनर्प्राप्त करने में सक्षम था। GetServiceC() विधि का उपयोग करके इच्छित के रूप में कार्य करता है, और मैं एक ही ऐप्स डोमेन में उपयोगकर्ताओं के लिए फ़ाइलों को पुनर्प्राप्त करने में सक्षम हूं।

यह चेक बॉक्स एक सेवा खाते के लिए टिक किए जाने की जरूरत है कि प्राधिकरण के डोमेन-व्यापी प्रतिनिधिमंडल के लिए पात्र होने के लिए है:

Creation of a new service account - DwD checkbox

यह एक बार आपके द्वारा किए गए अतिरिक्त जानकारी उपलब्ध है कि (कि के साथ एक throwaway सेवा खाते के साथ किया था नहीं बॉक्स टिक है, तुलना के लिए):

Comparison of service accounts with and without DwD

+0

मैंने कुंजी जेन यूआई पर नया डोमेन प्रतिनिधिमंडल विकल्प नहीं देखा था और इसे पहले कभी इसकी आवश्यकता नहीं थी - यह एक नई विशेषता होनी चाहिए। खुशी है कि तुम्हें इसका हल मिल गया! –

-2

अधिकांश सब कुछ ठीक लग रहा है लेकिन अगर वस्तु टाइपिंग मामलों लेकिन अपनी लाइन

ए का प्रयोग करें ServiceC कोड, यकीन नहीं कि सेवा सी में पी 12 फ़ाइल असली पी 12 फ़ाइल है जिसे आपने वास्तव में अपने पर्यावरण पर अपलोड किया है जहां आप इसे चला रहे हैं।

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

+0

ए 'var' का उपयोग करने से कोई फर्क नहीं पड़ता, https://msdn.microsoft.com/en-us/library/bb384061.aspx –

+0

(बी) देखें, मैं इसे अपनी स्थानीय मशीन पर चला रहा हूं; मैंने यह दिखाने के लिए कोड को स्पष्ट किया है कि मैं इसे सीधे App_Data फ़ोल्डर से लोड कर रहा हूं। (सी) मैंने फ़ाइल लिस्ट कमांड को निष्पादित करने के लिए वास्तविक कोड जोड़ा है (सभी GetService() विधियों के लिए आम) –

1

जब आप व्यवस्थापक पैनल पर सेवा खाता बनाते हैं, तो आप चेकबॉक्स जी सूट डोमेन-व्यापी प्रतिनिधि सक्षम कर सकते हैं।

सम्मान

+0

धन्यवाद, लेकिन जैसा कि आप देख सकते हैं मैं पहले से ही यह पता लगाने में कामयाब रहा हूं कि मैं गलत कहां जाऊंगा! :) –

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