c# - Google Calendar API 身份验证 .NET 浏览器窗口

标签 c# google-calendar-api google-api-dotnet-client

我使用的是最新版本的 Google .NET Client API (v1.81)。我正在尝试使用以下代码连接到日历服务

    var calendarService = new CalendarService(new BaseClientService.Initializer
    {
        HttpClientInitializer = GetCredential(),
        ApplicationName = "MyApp"
    });

    public UserCredential GetCredential()
    {
        UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            new ClientSecrets { ClientId = _clientId, ClientSecret = _clientSecret },
            new[] { CalendarService.Scope.Calendar }.ToList(), "user", CancellationToken.None,
            new FileDataStore("Drive.Auth.Store")).Result;

        return credential;
    }

当我这样做时,它会打开一个新的浏览器窗口并要求我进行身份验证。我之前已经过身份验证,并且通过 FileDataStore 存储和检索 key 。

为什么它会要求我再次进行身份验证?问题是因为此代码需要在后台服务中运行,因此无法打开浏览器选项卡。

我现在遇到的另一个问题是,当我尝试授权它打开一个新的浏览器窗口时,我选择了我的凭据,但登录页面随后告诉我

“请求中的重定向 URI:http://localhost:51773/authorize/ 与已注册的重定向 URI 不匹配”

为什么它尝试使用授权 url 而不是 AuthCallbackController。它还似乎随机更改重定向 uri 的端口号,使得无法注册。

最终的问题可能是,如果我有一个 Web 应用程序并且我希望用户通过网页使用他们的凭据登录,然后在以后的某个日期在服务器的后台任务中重用这些凭据,我该如何去那?我找不到任何相关的示例应用程序来展示如何操作。似乎 FileDataStore 不存储凭据,因此可以重复使用它们。我还实现了自己的 DataStore,将它们保存在数据库中,但似乎也不起作用。

进一步研究发现我需要 offline_access。我已经实现了与 Google Analytics OAuth with AccessType = Offline in C# 相同的方式但它仍然提示。如何重复使用 offline_access 刷新 token ?

最佳答案

您是对的,您需要创建自己的 Idatastore imp 实现。这将允许您将刷新 token 保存到数据库中并在以后使用。

这是一个非常粗略的例子

/// 
 /// Saved data store that implements . 
 /// This Saved data store stores a StoredResponse object.
 /// 
    class SavedDataStore : IDataStore
    {
        public StoredResponse _storedResponse { get; set; }
        /// 
        /// Constructs Load previously saved StoredResponse.
        /// 
        ///Stored response
        public SavedDataStore(StoredResponse pResponse)
        {
            this._storedResponse = pResponse;
        }
        public SavedDataStore()
        {
            this._storedResponse = new StoredResponse();
        }
        /// 
        /// Stores the given value. into storedResponse
        /// .
        /// 
        ///The type to store in the data store
        ///The key
        ///The value to store in the data store
        public Task StoreAsync(string key, T value)
        {
            var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
            JObject jObject = JObject.Parse(serialized);
            // storing access token
            var test = jObject.SelectToken("access_token");
            if (test != null)
            {
                this._storedResponse.access_token = (string)test;
            }
            // storing token type
            test = jObject.SelectToken("token_type");
            if (test != null)
            {
                this._storedResponse.token_type = (string)test;
            }
            test = jObject.SelectToken("expires_in");
            if (test != null)
            {
                this._storedResponse.expires_in = (long?)test;
            }
            test = jObject.SelectToken("refresh_token");
            if (test != null)
            {
                this._storedResponse.refresh_token = (string)test;
            }
            test = jObject.SelectToken("Issued");
            if (test != null)
            {
                this._storedResponse.Issued = (string)test;
            }
            return TaskEx.Delay(0);
        }

        /// 
        /// Deletes StoredResponse.
        /// 
        ///The key to delete from the data store
        public Task DeleteAsync(string key)
        {
            this._storedResponse = new StoredResponse();
            return TaskEx.Delay(0);
        }

        /// 
        /// Returns the stored value for_storedResponse      
        ///The type to retrieve
        ///The key to retrieve from the data store
        /// The stored object
        public Task GetAsync(string key)
        {
            TaskCompletionSource tcs = new TaskCompletionSource();
            try
            {
                string JsonData = Newtonsoft.Json.JsonConvert.SerializeObject(this._storedResponse);
                tcs.SetResult(Google.Apis.Json.NewtonsoftJsonSerializer.Instance.Deserialize(JsonData));
            }
            catch (Exception ex)
            {
                tcs.SetException(ex);
            }
            return tcs.Task;
        }

        /// 
        /// Clears all values in the data store. 
        /// 
        public Task ClearAsync()
        {
            this._storedResponse = new StoredResponse();
            return TaskEx.Delay(0);
        }

        ///// Creates a unique stored key based on the key and the class type.
        /////The object key
        /////The type to store or retrieve
        //public static string GenerateStoredKey(string key, Type t)
        //{
        //    return string.Format("{0}-{1}", t.FullName, key);
        //}
    }

现在您将调用 savedDataStore 而不是调用 filedatastore

 //Now we load our saved refreshToken. Probably from the DB someplace but this works
  StoredResponse myStoredResponse = new StoredResponse(tbRefreshToken.Text);
 // Now we pass a SavedDatastore with our StoredResponse.

credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
             new ClientSecrets { ClientId = "YourClientId", ClientSecret = "YourClientSecret" },
              new[] { DriveService.Scope.Drive,
                DriveService.Scope.DriveFile },
              "user",
              CancellationToken.None,
               new SavedDataStore(myStoredResponse)).Result; }

我有一个教程和示例项目。目前使用 Google Drive 范围,您可以轻松更改这些范围,示例项目位于底部。 Google Oauth2 C#

关于c# - Google Calendar API 身份验证 .NET 浏览器窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23669497/

相关文章:

c# - Google 日历事件未显示在日历中

c# - .net 内存使用情况,决定私有(private)字节大小的因素

c# - ElementHost 内的 WPF 控件不可见

c# - 为什么 C# 编译器使用无效方法的重载?

c# - 在 .NET 中将 Markdown 转换为 HTML

php - 在 iOS 应用程序上进行身份验证后,在 PHP 服务器上获取 Google 日历事件

python - 为什么 Gmail API 使用适用于 Google Calendar API 的代码会失败并出现 403 错误?

c# - 无法再下载文件

google-drive-api - 使用 .NET 客户端库上传大于 ~10MB 的文件时 Google Drive 上传失败

c# - 如果我已经拥有 Access Token 的值,如何创建 UserCredential 的实例?