google drive Api 无法在生产环境中工作“无法启动浏览器”

Posted

技术标签:

【中文标题】google drive Api 无法在生产环境中工作“无法启动浏览器”【英文标题】:google drive Api not working in production "Failed to launch browser with" 【发布时间】:2021-07-30 22:13:35 【问题描述】:

我遇到了 google drive API 的问题,它正在我的本地计算机上运行,​​但是一旦我将项目部署到服务器,google drive API 服务就会停止工作, 它引发了 oauth2 异常,我想我需要在 google drive api 控制台上做一些事情,但我不知道它是什么或从哪里开始 我当前使用的凭据是 OAuth 2.0 客户端 ID 和客户端密钥,键入 Desktop。

感谢您的帮助

这是我得到的例外。

  An unhandled exception occurred while processing the request.

AggregateException: One or more errors occurred. (Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=813040219774-atf2l4751d1tkjeegoeb7d4lituel9ev.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A42257%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive" for authorization. See inner exception for details.)
System.Threading.Tasks.Task<TResult>.GetResultCore(bool waitCompletionNotification)

NotSupportedException: Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=813040219774-atf2l4751d1tkjeegoeb7d4lituel9ev.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A42257%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive" for authorization. See inner exception for details.
Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.ReceiveCodeAsync(AuthorizationCodeRequestUrl url, CancellationToken taskCancellationToken)

Stack Query Cookies Headers Routing
AggregateException: One or more errors occurred. (Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=813040219774-atf2l4751d1tkjeegoeb7d4lituel9ev.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A42257%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive" for authorization. See inner exception for details.)
System.Threading.Tasks.Task<TResult>.GetResultCore(bool waitCompletionNotification)
ElseForty.FileServices.Files+GoogleDrive.GetService() in Files.cs
ElseForty.FileServices.Files+GoogleDrive.UploadFileAsync(IFormFile file) in Files.cs
ElseForty.Controllers.BugReportController.Send(User_BugReportViewModel model) in BugReportController.cs
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask<IActionResult> actionResultValueTask)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Show raw exception details
NotSupportedException: Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=813040219774-atf2l4751d1tkjeegoeb7d4lituel9ev.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A42257%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive" for authorization. See inner exception for details.
Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.ReceiveCodeAsync(AuthorizationCodeRequestUrl url, CancellationToken taskCancellationToken)
Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.AuthorizeAsync(string userId, CancellationToken taskCancellationToken)
Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(Initializer initializer, IEnumerable<string> scopes, string user, CancellationToken taskCancellationToken, IDataStore dataStore, ICodeReceiver codeReceiver)
Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(ClientSecrets clientSecrets, IEnumerable<string> scopes, string user, CancellationToken taskCancellationToken, IDataStore dataStore, ICodeReceiver codeReceiver)

Show raw exception details

更新

我正在为我的网络应用程序使用 google drive api 供访客上传图片,

          public static DriveService GetService()
        
            UserCredential credential;

            using (var stream =
              new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
            
                string credPath = "token.json";
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    scopes,
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true)).Result;
                Console.WriteLine("Credential file saved to: " + credPath);
            

            return new DriveService(new BaseClientService.Initializer()
            
                HttpClientInitializer = credential,
                ApplicationName = "elsefortydisk",
            );
        

        public static async Task<string> UploadFileAsync(IFormFile file)
        
            var fileName = GetUniqueFileName(file.FileName);
            var service = GetService();
            var fileMetadata = new Google.Apis.Drive.v3.Data.File();
            fileMetadata.Name = Path.GetFileName(fileName);
            fileMetadata.MimeType = file.ContentType;
            fileMetadata.Parents = new List<string>()  "14kECd48VL6xhS9ArQL3Lh7oLT6npAVg-" ;

            FilesResource.CreateMediaUpload request;
            using (var stream = file.OpenReadStream())
            
                request = service.Files.Create(fileMetadata, stream, file.ContentType);

                request.Fields = "id";
                await request.UploadAsync();
            
            var responce = request.ResponseBody;
            var pemission = new Permission();
            pemission.Type = "anyone";
            pemission.Role = "reader";
            try
            
                service.Permissions.Create(pemission, responce.Id).Execute();  
            
            catch (Exception e)
            
                Console.WriteLine("An error occurred: " + e.Message);
            

            return responce.Id;
        

【问题讨论】:

请编辑您的问题并包含minimal reproducible example,而不会看到您的代码很难提供帮助 嗨@DaImTo 我在上面包含了一些代码,希望这可以帮助你更好地理解我想要做的事情,thanx 我更新了我的答案,以更好地解释为什么您不能将 GoogleWebAuthorizationBroker.AuthorizeAsync 用于 Web 应用程序,并向您展示您应该如何编码您的应用程序。 【参考方案1】:

您的问题已将您的问题标记为 asp.net core,并声明您正在将其上传到服务器。然而,你还说你在谷歌开发者控制台上创建了一个桌面客户端

我当前使用的是 OAuth 2.0 客户端 ID 和客户端密钥,请键入 Desktop。

如果您使用的是 asp .net core,那么您正在创建一个 Web 应用程序,并且应该已经创建了 Web 浏览器凭据。

您使用的代码是为已安装/桌面应用程序设计的,该代码在用户使用的机器上运行。示例 您正在使用GoogleWebAuthorizationBroker.AuthorizeAsync,它旨在与已安装的应用程序一起使用。它的设计方式是在运行它的机器上打开浏览器窗口,这就是您看到以下错误消息的原因。

NotSupportedException:无法使用“https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=813040219774-atf2l4751d1tkjeegoeb7d4lituel9ev.apps.googleusercontent.com&redirect_uri=http%3A%2F %2F127.0.0.1%3A42257%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive" 用于授权。有关详细信息,请参阅内部异常。

您的代码在本地工作,因为它能够在其运行的机器上打开浏览器窗口,当它在 Web 服务器上运行时,它将尝试在 Web 服务器上打开 Web 浏览器同意窗口,这不是您想要的您是否希望它在用户客户端计算机上打开浏览器同意。

如果您尝试使用 Asp .net core 创建 Web 应用程序,则需要创建 Web 应用程序凭据,并按如下方式配置 Web 应用程序。

配置一个 asp.net 核心应用程序来访问 google api 是完全不同的,我在这里有一个教程,它将引导你完成设置的配置,但是 Asp .net core 3 and Google login

// This configures Google.Apis.Auth.AspNetCore3 for use in this app.
 services
     .AddAuthentication(o =>
     
         // This forces challenge results to be handled by Google OpenID Handler, so there's no
         // need to add an AccountController that emits challenges for Login.
         o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
         // This forces forbid results to be handled by Google OpenID Handler, which checks if
         // extra scopes are required and does automatic incremental auth.
         o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
         // Default scheme that will handle everything else.
         // Once a user is authenticated, the OAuth2 token info is stored in cookies.
         o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
       )
       .AddCookie()
       .AddGoogleOpenIdConnect(options =>
       
          options.ClientId = ClientId;
          options.ClientSecret = ClientSecret;
           );

调用请求授权的api本身主要是通过一个属性来完成的。

[GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
public async Task<IActionResult> DriveFileList([FromServices] IGoogleAuthProvider auth)

    GoogleCredential cred = await auth.GetCredentialAsync();
    var service = new DriveService(new BaseClientService.Initializer
    
        HttpClientInitializer = cred
    );
    var files = await service.Files.List().ExecuteAsync();
    var fileNames = files.Files.Select(x => x.Name).ToList();
    return View(fileNames);

提示

桌面/已安装的应用程序设计为在用户面前并使用的单台机器上运行。

Web 应用程序从 Web 服务器运行,用户通过 Web 浏览器联系它们。

这是两种不同类型的应用程序,在谷歌开发者控制台上创建的客户端不同,使用这些客户端的代码也不同。

【讨论】:

如果你有兴趣,我有一个示例项目,我可以在 GitHub 上发布带有 asp .net core 的 Google drive api thanx,是的,这将有很大帮助,我做了一些更改,它看起来像是在工作一半,我将应用程序类型更改为 Web 应用程序,“以前是桌面应用程序”。我还更改了代码以请求驱动服务实例以适应新的应用程序类型,但现在我在用户登录后被重定向到此 URL。 mywebsite.com/signin-oidc。我的项目中没有这个控制器“signin-oidc”,我希望用户改为转到“google drive upload image”操作。我该怎么做? Google Drive Asp .Net core sample Oauth 的工作方式是,您的应用程序将上传图像,用户无需前往 Google Drive 上传图像,一旦他们授予您的应用程序访问权限,您就可以为他们执行此操作到他们的驱动器帐户。请记住,当您申请验证此应用程序时,Google Drive 被视为您必须通过安全审核的受限范围。 What you need to know about application verification in 2021 我明白了,看起来这个过程不是我想要的,我不希望我的用户在他们只想上传图像时被要求授予任何权限,这将看起来超级可疑,我会放弃这个并将所有内容上传到我的服务器我猜,谢谢你的大力帮助

以上是关于google drive Api 无法在生产环境中工作“无法启动浏览器”的主要内容,如果未能解决你的问题,请参考以下文章

无法从 Google Drive API 检索 thumbnailLink

Google Drive API无法找到任何文件夹

无法从Google Drive API检索文件内容

在 Laravel 5 中使用 Google Drive Api

使用 REST api 从 Google Drive 下载图片

Google Drive API,无法通过 JS 打开标准共享对话框(x-frame-options 错误)