c# - 从 Azure 调用 Google API : "Access is denied"

标签 c# azure google-api google-oauth google-api-dotnet-client

我正在尝试创建一个可以管理 Google 日历并访问 Google People 的聊天机器人。我开发了代码,它可以完美地离线工作。当尝试在线上传所有内容时就会出现问题。

代码采用C#语言,在微软提供的模板之上开发。当您在 Azure 上加载代码时,LUIS 的功能可以正常工作,但当您调用 Google API 时就会出现问题。出现的错误如下:

System.AggregateException: One or more errors occurred. —> System.Net.HttpListenerException: Access is denied at System.Net.HttpListener.SetupV2Config() at System.Net.HttpListener.Start() at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.StartListener() at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.d__14.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.d__8.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__4.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext() — End of inner exception stack trace — at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at Microsoft.Bot.Sample.LuisBot.Dialogs.LinkContact.ConnectPeople() at Microsoft.Bot.Sample.LuisBot.Dialogs.LinkContact.GetUserName() —> (Inner Exception #0) System.Net.HttpListenerException (0x80004005): Access is denied at System.Net.HttpListener.SetupV2Config() at System.Net.HttpListener.Start() at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.StartListener() at Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.d__14.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.d__8.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__4.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext()<—

在网上我发现了很多类似问题的案例,不幸的是,很少有人得到解答,而且在少数答案中,没有一个能解决问题。有人有什么想法吗?

我关注的最后一点之一链接到此报告 https://github.com/google/google-api-dotnet-client/issues/908 ,在某个时候它说:

"Sounds like its trying to launch the browser on the server and not on the users browser. It works on localhost because you have the power to launch a new browser session on your local pic. The problem comes when you try and deploy it and it trys to launch browser on the server rather in a new client browser. You should be following this authweb apps https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#web-applications-aspnet-mvc"

不知道是不是这个问题。我尝试点击该链接,但无法将这些说明与我的代码集成。

这是我的身份验证代码:

  private static PeopleServiceService ConnectPeople()
    {
        // Create OAuth credential.
     CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;
        IDataStore credentialPersistanceStore   = new Dialogs.myDataStore();

        Task<UserCredential> result = GoogleWebAuthorizationBroker.AuthorizeAsync(
          new ClientSecrets
          {
              ClientId = "*id*",
              ClientSecret = "*secret*"
          },
          new[] { "profile", "https://www.googleapis.com/auth/contacts.readonly" },
        "me",token,
          credentialPersistanceStore);

        result.Wait();
        UserCredential credential = result.Result;

        // Create the service.
        var service = new PeopleServiceService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "*nome*",
        });

        return service;
    }

然后我使用“服务”来使用 Google API。

我的工作经历如下: https://developers.google.com/google-apps/calendar/quickstart/dotnethttps://dev.botframework.com/ .

谢谢大家

最佳答案

您正在关注的教程 .NET Quickstart设计用于与 .NET 控制台应用程序一起使用。它之所以有效,是因为它会生成 Web 浏览器以在本地计算机上进行身份验证。当您尝试将其部署到 Web 服务器时,它不会工作,因为您无法在 Web 服务器上生成浏览器,您需要在用户计算机上生成它。

您应该按照此进行身份验证 Web applications (ASP.NET MVC)

using System;
using System.Web.Mvc;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.Drive.v2;
using Google.Apis.Util.Store;

namespace Google.Apis.Sample.MVC4
{
    public class AppFlowMetadata : FlowMetadata
    {
        private static readonly IAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = "PUT_CLIENT_ID_HERE",
                        ClientSecret = "PUT_CLIENT_SECRET_HERE"
                    },
                    Scopes = new[] { DriveService.Scope.Drive },
                    DataStore = new FileDataStore("Drive.Api.Auth.Store")
                });

        public override string GetUserId(Controller controller)
        {
            // In this sample we use the session to store the user identifiers.
            // That's not the best practice, because you should have a logic to identify
            // a user. You might want to use "OpenID Connect".
            // You can read more about the protocol in the following link:
            // https://developers.google.com/accounts/docs/OAuth2Login.
            var user = controller.Session["user"];
            if (user == null)
            {
                user = Guid.NewGuid();
                controller.Session["user"] = user;
            }
            return user.ToString();

        }

        public override IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }
}

关于c# - 从 Azure 调用 Google API : "Access is denied",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48265391/

相关文章:

c# - 如何在 C# 中获取存储过程的返回值?

C#:如何知道是否安装了某个Office 2003或2007应用程序?

python - 在 Azure Cosmos DB 中插入时分区键不起作用

azure - 使用 Spark 和 azure 进行批处理

azure - 使用 AZCopy 插入带有原始时间戳的 Azure 表

google-apps-script - 在 1 个 zip 中压缩多个文件夹 - Google Drive Scripts

python - Google Drive API Python 实现的 ~/.credentials/drive-python-quickstart.json 保存在哪里?

c# - 如何使用 WinSCP 和 C# 从服务器获取 SSH 指纹

google-api - 为 google plus 交换 oauth2 token 时出现 "policy_enforced"错误

c# 运行时参数值的反射电流