尝试访问 Google Drive 时服务器超时,在本地运行时有效

Posted

技术标签:

【中文标题】尝试访问 Google Drive 时服务器超时,在本地运行时有效【英文标题】:Server time-out when trying to access Google Drive, works when running locally 【发布时间】:2022-01-18 00:54:48 【问题描述】:

我有一个使用 .NET API v3 访问 Google Drive 的 ASP.NET 网站。我按照.NET Quickstart 创建凭据并生成令牌。 JSON 凭证文件的redirect_urls 部分如下所示...

"redirect_uris": [
  "http://127.0.0.1/authorize/",
  "http://127.0.0.1/authorize",
  "https://127.0.0.1/authorize/",
  "https://127.0.0.1/authorize"
],

这一切都在本地正常工作。当我调试站点时,它会弹出 Google oAuth 屏幕,并要求我进行身份验证。完成后,该网站运行良好,访问 Google 云端硬盘的页面也可以正常运行。

我现在想部署到临时站点,因此创建了新的 oAuth 凭据,使用与以前相同的详细信息,但使用站点的域而不是 127.0.0.1。但是,当我部署站点时,任何尝试加载访问 Google 的页面都会导致超时。

服务器上的事件查看器显示以下错误(敏感数据被混淆)...

System.Net.HttpListenerException (5): Access is denied.
   at System.Net.HttpListener.AddPrefixCore(String registeredPrefix)
   at System.Net.HttpListener.AddAllPrefixes()
   at System.Net.HttpListener.Start()
   at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.StartListener()
   at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.ReceiveCodeAsync(AuthorizationCodeRequestUrl url, CancellationToken taskCancellationToken)
   at Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.AuthorizeAsync(String userId, CancellationToken taskCancellationToken)
   at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(Initializer initializer, IEnumerable`1 scopes, String user, CancellationToken taskCancellationToken, IDataStore dataStore, ICodeReceiver codeReceiver)
   at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(ClientSecrets clientSecrets, IEnumerable`1 scopes, String user, CancellationToken taskCancellationToken, IDataStore dataStore, ICodeReceiver codeReceiver)
   at Microsoft.AspNetCore.Components.Rendering.htmlRenderer.HandleException(Exception exception)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters)
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)
   at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)
   at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c__11`1.<<InvokeAsync>b__11_0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, Type componentType, RenderMode renderMode, Object parameters)
   at Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
   at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, Int32 i, Int32 count)
   at MyWebSite.Areas.General.Pages.Areas_General_Pages__Host.<ExecuteAsync>b__14_1() in C:\PathToWebSite\Areas\General\Pages\_Host.cshtml:line 24
   at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
   at MyWebSite.Areas.General.Pages.Areas_General_Pages__Host.ExecuteAsync() in C:\PathToWebSite\Areas\General\Pages\_Host.cshtml:line 6
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

我几乎看起来好像它试图在服务器上的浏览器窗口中弹出 oAuth 页面(它不会管理,因为不会有与运行 IIS 的用户关联的桌面),然后等待某人使用该页面时超时。我可能是错的,但如果我是对的,我不明白它为什么要这样做,因为为 Web 应用程序创建凭据的全部意义在于验证的人不会在服务器上。但是,无论如何,我可能完全错了这个假设!

该网站是使用 Blazor 编写的,但我认为这无关紧要,因为我添加了一个 MVC 控制器作为测试,并且遇到了完全相同的问题。

有人知道为什么会发生这种情况,我能做些什么吗?谢谢。

【问题讨论】:

我猜您只是将本地 IP 添加到了身份验证客户端的 authorized redirect URIs。我建议将一组凭据用于 prod,一组用于 staging,一组用于 dev。使用 .NET 配置为每个环境设置它们。 您需要在 Google OAuth 设置中将完全限定的重定向 URI 列入白名单,包括 www 或非 www(取决于您使用的是什么) @foxtrotuniform6969 不确定您的意思。我确实为暂存站点创建了一组新凭据(请参阅我的第 3 段),并使用站点的域而不是我的本地 IP。我误会你了吗? @PramiGawande 请您解释一下您的意思。我在哪里将 URI 列入白名单?如果您的意思是将它们添加到凭据中的“授权重定向 URI”中,那么我使用该站点使用的确切 URI 来执行此操作(请参阅我的第 3 段)。请你澄清你的意思。谢谢 @Avrohom 我的意思是添加 URI 的 www 和非 www 版本,例如 http://example.com 和 http://www.example.com 我遇到了同样的问题问题有时回来。此外,如果您在控制台中遇到任何其他错误,请检查开发人员工具。 【参考方案1】:

如果您使用的是该快速入门中的代码,那么它将无法在网络应用中运行。那里的代码用于桌面应用程序,并使用您的浏览器打开 oAuth 屏幕。

那个页面真的没有说清楚,我从this comment GitHub 问题上找到了这个。引用(包括拼写错误!)...

GoogleWebAuthorizationBroker.AuthorizeAsync 适用于已安装的应用程序。它会尝试在服务器上打开授权 Web 浏览器,但无法正常工作。

你需要Web applications (ASP.NET MVC)

但是,该链接中的代码适用于 MVC,我不知道它是否适用于 Blazor,因为 auth 是一个全新的球类游戏。如果您阅读了该 GitHub 问题中的先前评论,您将看到建议您在应用程序的标准 ASP.NET Core 部分中执行用户身份验证,然后将 IGoogleAuthProvider 传递给 Blazor。

希望对您有所帮助,即使这不是您想听到的!

【讨论】:

以上是关于尝试访问 Google Drive 时服务器超时,在本地运行时有效的主要内容,如果未能解决你的问题,请参考以下文章

Google Drive api范围和文件访问(驱动器vs drive.files)

如何创建具有 Google Drive 访问权限的服务帐户

如何从我的应用程序访问 google drive api

用于复制整个 Google Drive 文件结构的 Google Apps 脚本;如何避免超时?

Google Drive API(Driver.Builder)身份验证问题:NullPointerException前置条件检查

使用 Google Datalab,尝试从 Google Drive 导入数据