我参与构建了一个内部使用的应用程序,用户可以通过该应用程序上传文件以存储在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上注册。” –