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

时间:2014-05-15 04:52:25

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

我使用的是最新版本的Google .NET客户端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存储和检索的。

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

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

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

为什么要尝试使用Authorize url而不是AuthCallbackController。它似乎也随机改变了重定向uri的端口号,使其无法注册。

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

进一步深入研究这似乎我需要offline_access。我已经像Google Analytics OAuth with AccessType = Offline in C#那样实现了它,但它仍然提示。如何重用offline_access刷新令牌?

1 个答案:

答案 0 :(得分:2)

您是正确的,您需要创建自己的Idatastore实现。这将允许您将刷新令牌保存到数据库并在以后使用它。

这是一个非常粗略的例子

/// 
 /// 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);
        //}
    }

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

 //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#