我參與構建了一個內部使用的應用程序,用戶可以通過該應用程序上傳文件以存儲在Google雲端硬盤中。由於建議不要將服務帳戶用作文件所有者,因此我希望代表系統管理員可訪問的指定用戶帳戶上載應用程序。將Google雲端硬盤授權給服務帳戶失敗
我已經創建了應用程序以及一個服務帳戶。有服務帳戶創建了兩個按鍵,因爲我已經試用過JSON和PKCS12格式努力實現這一點:
我已經下載了OAuth 2.0用戶端ID的詳細信息,也有以.json服務帳戶鍵或.p12文件(在按以上順序顯示):
我有我的系統經過這裏的詳細步驟把權力用於服務帳戶驅動器的API訪問:https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account
我們發現在第4步中唯一適用於「客戶端名稱」的是爲Web應用程序列出的「客戶端ID」(結束.apps.googleusercontent.com)。爲服務帳戶鍵列出的長十六進制的ID是不是需要它(見下文):
此前上述,我有代碼這將創建一個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;
}
,對於上市和上傳作品,當然雖然有用於訪問文件中沒有網絡用戶界面,它好像它不處理諸如權限元數據或生成縮略圖等PDF文件。這就是我試圖使用標準帳戶進行上傳的原因。
一旦代表團顯然被排序,我然後嘗試調整上面鏈接的委託引用中顯示的代碼,並結合其他地方的代碼從.json密鑰文件中提取必要的詳細信息。有了這個代碼,只要我努力,以執行任何API命令,即使是簡單的:
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();
最後一行出現異常。
我不明白爲什麼我的服務帳戶無法代表指定的用戶,這是應用程序的服務帳戶應授權的域的一部分。我在這裏誤解了什麼?
這可能是一個配置錯誤的問題。您是否在客戶名稱中輸入了服務帳戶的客戶ID?它是[委託服務帳戶的全域授權]中的第5步(https://developers.google.com/drive/v2/web/delegation#delegate_domain-wide_authority_to_your_service_account) – noogui
@noogui生成的.json文件用於服務帳戶密鑰包含「client_id」條目,該條目是21位十進制數字。在步驟#5中使用它會顯示一條錯誤消息:「此客戶名稱尚未在Google上註冊。」 –