C# Google Drive 获取文件返回无效算法

Posted

技术标签:

【中文标题】C# Google Drive 获取文件返回无效算法【英文标题】:C# Google Drive Get File return Invalid Algorithm 【发布时间】:2022-01-01 19:06:43 【问题描述】:

我被这个问题困住了。我正在使用带有 P12 文件的 C# 中的 Google Drive。它在我的本地机器和服务器上运行良好。我需要将它部署在客户端新服务器上,当我尝试获取返回无效算法的文件时遇到此问题。相同的设置在我的本地机器和其他服务器上工作正常。这似乎是机器特定的问题。应用程序在 Windows 7 Professional 64 位操作系统上运行。 服务已成功创建证书已读取但以下代码返回错误这是我返回错误的代码

FilesResource.ListRequest list = service.Files.List();
list.PageSize = 100;
            
files = list.Execute().Files; /// This line has error

可能是防火墙问题。防火墙应该打开什么?

这是我的授权码:

public override DriveService AuthenticateServiceAccount(DriveRequest request)
    
        if (request == null)
            return null;
        string errorMessage = "Exception: invalid Drive Request";
        if (string.IsNullOrEmpty(request.EmailAccount) || string.IsNullOrEmpty(request.KeyFilePath))
            return null;
        errorMessage = "Exception: Keyfile not found on the path-" + request.KeyFilePath;
        // check the file exists
        if (!System.IO.File.Exists(request.KeyFilePath))
        
            Commons.Utilities.WriteLog(errorMessage);                
            return null;
        

      

        //---- This scope is used For G-Suite Account
        string[] scopes = new string[]  DriveService.Scope.Drive ;  
        errorMessage = "Exception: issue with certificate";

        var certificate = new X509Certificate2(request.KeyFilePath, "notasecret", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
        try
        
            ServiceAccountCredential credential = null;
            if (request.UserAccount != "" && request.UserAccount != null)
            
                credential = new ServiceAccountCredential(
                    new ServiceAccountCredential.Initializer(request.EmailAccount)
                    
                        Scopes = scopes,
                        User = request.UserAccount
                    .FromCertificate(certificate));
            
            else 
                credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(request.EmailAccount)
                
                    Scopes = scopes
                .FromCertificate(certificate));
            
            errorMessage = "Exception: while creating google service";
            if (service == null) 
                // Create the service.
                service = new DriveService(new BaseClientService.Initializer()
                
                    HttpClientInitializer = credential,
                    ApplicationName = "Simplicity Cloud Project" // User defined any name can be given
                ) ;
            
            return service;
        
        catch (Exception ex)
        
            //Console.WriteLine(ex.InnerException);
            Commons.Utilities.WriteLog(errorMessage);
            return null;
        
    

这是生成的日志:

读取证书 2021-11-22 15:25:58,416 |SimplicityOnlineWebApi.Commons.Utilities|信息| - 证书已读:[主题] CN=102737515943555401961

[发行人] CN=102737515943555401961

[序列号] 1E269224F694B808

[不是之前] 2016 年 2 月 9 日 16:24:59

[不是之后] 2026 年 8 月 31 日 16:24:59

[指纹] C26D88E95B402EFCC1AC81230F89C0B7887A6C6A

2021-11-22 15:25:58,445 |SimplicityOnlineWebApi.Commons.Utilities|INFO| - 创建服务 2021-11-22 15:25:58,455 |SimplicityOnlineWebApi.Commons.Utilities|INFO| - 服务已成功创建 Google.Apis.Drive.v3.DriveService

2021-11-22 15:25:58,528 |SimplicityOnlineWebApi.Commons.Utilities|INFO| - GetFiles 发生错误:指定的算法无效。

这里是GetFile方法的代码

Here is code:public override AttachmentFilesFolder GetFiles(DriveService service, string search)
    
        AttachmentFilesFolder attachments = null;
        IList<File> files = new List<File>();
        
        try
        
            //List all of the files and directories for the current user.  
            FilesResource.ListRequest list = service.Files.List();
            list.PageSize = 100;
            Utilities.WriteLog("Getting files");
            files = list.Execute().Files;
        
        catch (Exception ex)
        
            Utilities.WriteLog("Error occured in GetFiles:" + ex.message);
        

【问题讨论】:

请完整的错误消息和堆栈跟踪。 请编辑您的问题并包含您的授权码以及错误消息。如果您认为这与 p12 文件有关,为什么不发布您的授权代码? TBH,您不应该使用 p12 文件,而应该将 Json 密钥文件用于服务帐户,这样可以更轻松地解决您现在遇到的问题。 GetFiles 是什么,我们可以看看那个方法吗? 您在 SimplicityOnlineWebApi.Commons.Utilities 中有一个名为 GetFiles 的方法向我们展示了这一点。 我已经提到了有错误的代码。这实际上是在 GetFile 方法中。我再次编辑了代码。请评价一下 【参考方案1】:

P12 文件的问题。

使用 p12 密钥文件授权服务帐户的问题通常与 X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable 行有关,如果我记得它与密钥在服务器上的存储位置和方式有关。话虽如此,当应用程序托管在 Azure 中并且错误消息与您所看到的内容不同时也是如此。几年前我写了一篇关于它的博文Azure with service accounts in C#

这是我用于 p12 文件的代码

var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
        
        Scopes = scopes
        .FromCertificate(certificate));

// Create the  Drive service.
return new DriveService(new BaseClientService.Initializer()
       
        HttpClientInitializer = credential,
        ApplicationName = "Drive Authentication Sample",
        );

Json 密钥文件

老实说,您不应该费心使用 p12 文件,而应该将 json 密钥文件用于服务帐户,这更容易使用,并且您不会遇到服务器给您 greif 的问题。

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

                // Create the  Analytics service.
                return new DriveService(new BaseClientService.Initializer()
                
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Service account Authentication Sample",
                );

【讨论】:

感谢您的回复。您可以看到我如何使用证书的代码。和你在帖子中描述的一样。重要的是我的代码在所有其他机器上都可以正常工作 我认为这不是您的服务帐户的问题。 是的,你是对的。它似乎是特定于机器的。如果服务帐户有问题,那么它根本不应该工作。但它在所有其他机器上都可以正常工作 查看我对您应该只使用的 P12 文件的评论 X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportabl 但是正如您在日志中看到的,我们成功获得了证书【参考方案2】:

我相当确定您的代码、服务帐户或 Google 客户端库中没有任何内容会引发此错误。我认为正在发生的事情:

ServiceAccountCredential 在发出身份验证请求时使用 SHA256 对有效负载进行签名。 您收到的错误表明您的机器当前不支持 SHA256。

旧版本的 Windows 7 不支持 SHA256。您可以在此处阅读更多相关信息:2019 SHA-2 Code Signing Support requirement for Windows and WSUS,其中还列出了您需要为 Windows 7 机器安装的更新以支持 SHA256。

如果在检查您的系统是最新的之后,您仍然收到相同的错误,这仍然表明您的环境中存在一些 SHA256 不兼容。 Why am I getting "Invalid algorithm specified" exception 这里有一个很长的帖子,其中包含针对不同原因的修复/解决方法,其中一些可能适用于您。

【讨论】:

以上是关于C# Google Drive 获取文件返回无效算法的主要内容,如果未能解决你的问题,请参考以下文章

Node JS Google Drive api方法列表返回已删除文件

请求AppDataFolder时,Google云端硬盘API会返回错误“无效值”和“无效查询”

cron 运行网站备份 google drive api 脚本时出现“无效授权”错误

从 URL 列表中获取文件名 - Google Drive

React-native Google Drive如何获取文件和文件夹列表?

获取Google Drive演示文稿文件的链接