从Azure调用Google API:"访问被拒绝"

时间:2018-01-15 14:53:43

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

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

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

  

System.AggregateException:发生了一个或多个错误。 - >   System.Net.HttpListenerException:拒绝访问   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()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.d__8.MoveNext()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__4.MoveNext()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext()    - 内部异常堆栈跟踪结束 - at   System.Threading.Tasks.Task.ThrowIfExceptional(布尔   includeTaskCanceledExceptions)at   System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout,   取消语音取消语言)   Microsoft.Bot.Sample.LuisBot.Dialogs.LinkContact.ConnectPeople()at at   Microsoft.Bot.Sample.LuisBot.Dialogs.LinkContact.GetUserName() - >   (内部异常#0)System.Net.HttpListenerException(0x80004005):   在System.Net.HttpListener.SetupV2Config()处拒绝访问   System.Net.HttpListener.Start()at   Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.StartListener()at   Google.Apis.Auth.OAuth2.LocalServerCodeReceiver.d__14.MoveNext()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.AuthorizationCodeInstalledApp.d__8.MoveNext()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__4.MoveNext()    - 从抛出异常的先前位置开始的堆栈跟踪结束   - 在   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)   Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.d__1.MoveNext()< -

在线查看我发现很多类似问题的案例,遗憾的是,很少有人回答过,在少数答案中,没有一个能解决问题。有没有人有任何想法?

我关注的最后一点与此报告https://github.com/google/google-api-dotnet-client/issues/908相关联,在某些时候它会说:

  

"听起来像是试图在服务器上启动浏览器而不是   用户浏览器。它适用于localhost,因为你有权力   在您的本地图片上启动新的浏览器会话。问题来了   您尝试部署它并尝试在服务器上启动浏览器   而是在新的客户端浏览器中。你应该关注这个authweb   应用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;
    }

然后我使用&#34; service&#34;使用Google API。

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

感谢所有人

1 个答案:

答案 0 :(得分:1)

您所关注的教程.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; }
        }
    }
}