首页 > 解决方案 > google drive Api 无法在生产环境中工作“无法启动浏览器”

问题描述

我遇到了 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

更新

我正在为我的 Web 应用程序使用 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;
        }

标签: google-apigoogle-drive-apiasp.net-core-mvcgoogle-oauthgoogle-api-dotnet-client

解决方案


问题 您已将问题标记为 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 核心创建 Web 应用程序,则需要创建 Web 应用程序凭据,并按如下方式配置 Web 应用程序。

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

// 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 浏览器联系它们。

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


推荐阅读