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

Server time-out when trying to access Google Drive, works when running locally

我有一个 ASP.NET 网站可以使用 .NET API v3 访问 Google 驱动器。我按照 .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 Drive 的页面也可以。

我现在想部署到暂存站点,因此创建了新的 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)

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

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

有谁知道为什么会这样,我能做些什么吗?谢谢。

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

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

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

您将需要 Web applications (ASP.NET MVC)

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

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