Google Calendar API v3 – 在服务器上部署时请求超时

我试图登录localhost,一切正常。

代码:

public static bool LoginGoogleCalendar(string clientId, string clientSecret, string idGCalendarUser, string calendarServiceScope, string folder) { try { UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret, }, new[] { calendarServiceScope }, idGCalendarUser, CancellationToken.None, new FileDataStore(folder)).Result; return true; } catch (Exception ex) { Elmah.ErrorSignal.FromCurrentContext().Raise(ex); return false; } } 

(我正确设置了fileDataStore的授权)

在Google Developers Console中:

重定向URI: http://localhost/authorize/ Javascript起源: http://localhost:8081

我使用Visual Studio 2013,IIS 8

当我尝试登录服务器时,会阻塞整个服务器几分钟,之后的答案是:System.Web.HttpException请求超时。

在Google Developers Console中:

重定向URI: http://pippo.pluto.it/authorize/http://pippo.pluto.it/authorize/ Javascript起源: http://pippo.pluto.ithttp://pippo.pluto.it

在服务器上:IIS 7

对我的示例的引用: https : //developers.google.com/google-apps/calendar/instantiate

我走到了同样的问题。 互联网上的很多例子告诉你使用这个课程。 对于Web应用程序,这不是要使用的类。 这个类适用于“离线”应用程序,但是当你在IIS服务器上使用这个类时,它会尝试打开服务器上的弹出窗口,但它不会让它。

我使用的课程:GoogleAuthorizationCodeFlow

 using Google.Apis.Analytics.v3; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using Google.Apis.Auth.OAuth2.Requests; using Google.Apis.Auth.OAuth2.Web; using Google.Apis.Services; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web; namespace GoogleOauth2DemoWebApp { public class GoogleOauth { public AnalyticsService Handle(string _userId, string _connectionString, string _googleRedirectUri, string _applicationName, string[] _scopes) { try { string UserId = _userId;//The user ID wil be for examlpe the users gmail address. AnalyticsService service; GoogleAuthorizationCodeFlow flow; //use extended class to create google authorization code flow flow = new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer { DataStore = new DbDataStore(_connectionString),//DataStore class to save the token in a SQL database. ClientSecrets = new ClientSecrets { ClientId = "XXX-YOUR CLIENTID-XXX", ClientSecret = "XXX-YOURCLIENTSECRET-XXX" }, Scopes = _scopes, }); var uri = HttpContext.Current.Request.Url.ToString(); string redirecturi = _googleRedirectUri;//This is the redirect URL set in google developer console. var code = HttpContext.Current.Request["code"]; if (code != null) { var token = flow.ExchangeCodeForTokenAsync(UserId, code, uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result; var test = HttpContext.Current.Request["state"]; // Extract the right state. var oauthState = AuthWebUtility.ExtracRedirectFromState( flow.DataStore, UserId, HttpContext.Current.Request["state"]).Result; HttpContext.Current.Response.Redirect(oauthState); } else { var result = new AuthorizationCodeWebApp(flow, redirecturi, uri).AuthorizeAsync(UserId, CancellationToken.None).Result; if (result.RedirectUri != null) { // Redirect the user to the authorization server. HttpContext.Current.Response.Redirect(result.RedirectUri); } else { // The data store contains the user credential, so the user has been already authenticated. service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = result.Credential, ApplicationName = _applicationName }); return service; } } return null; } catch (Exception ex) { throw ex; } } internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow { public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { } public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri) { var ss = new Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl)); ss.AccessType = "offline"; ss.ApprovalPrompt = "force"; ss.ClientId = ClientSecrets.ClientId; ss.Scope = string.Join(" ", Scopes); ss.RedirectUri = redirectUri; return ss; } }; } } 

我也用一个DataStore类。 将令牌保存到服务器上的文件不是最佳做法。 我用了一个SQL数据库。

数据存储类的示例。 它会为你制作一张桌子,而不是最好的方法,但测试足够好。

 using Google.Apis.Json; using Google.Apis.Util.Store; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GoogleOauth2DemoWebApp { public class DbDataStore : IDataStore { readonly string connectionString; public string ConnectionString { get { return connectionString; } } private Boolean _ConnectionExists { get; set; } public Boolean connectionExists { get { return _ConnectionExists; } } ///  /// Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist /// yet) under the current directory ///  /// Folder name public DbDataStore(String _connectionString) { connectionString = _connectionString; SqlConnection myConnection = this.connectdb(); // Opens a connection to the database. if (_ConnectionExists) { // check if the Table Exists; try { SqlDataReader myReader = null; SqlCommand myCommand = new SqlCommand("select 1 from GoogleUser where 1 = 0", myConnection); myReader = myCommand.ExecuteReader(); while (myReader.Read()) { var hold = myReader["Column1"]; } } catch { // table doesn't exist we create it SqlCommand myCommand = new SqlCommand("CREATE TABLE [dbo].[GoogleUser]( " + " [username] [nvarchar](4000) NOT NULL," + " [RefreshToken] [nvarchar](4000) NOT NULL," + " [Userid] [nvarchar](4000) NOT NULL" + " ) ON [PRIMARY]", myConnection); myCommand.ExecuteNonQuery(); } } myConnection.Close(); } ///  /// Stores the given value for the given key. It creates a new file (named ) in /// . ///  /// 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) { if (string.IsNullOrEmpty(key)) { throw new ArgumentException("Key MUST have a value"); } var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value); SqlConnection myConnection = this.connectdb(); if (!_ConnectionExists) { throw new Exception("Not connected to the database"); } // Try and find the Row in the DB. using (SqlCommand command = new SqlCommand("select Userid from GoogleUser where UserName = @username", myConnection)) { command.Parameters.AddWithValue("@username", key); string hold = null; SqlDataReader myReader = command.ExecuteReader(); while (myReader.Read()) { hold = myReader["Userid"].ToString(); } myReader.Close(); if (hold == null) { try { // New User we insert it into the database string insertString = "INSERT INTO [dbo].[GoogleUser] ([username],[RefreshToken],[Userid]) " + " VALUES (@key,@value,'1' )"; SqlCommand commandins = new SqlCommand(insertString, myConnection); commandins.Parameters.AddWithValue("@key", key); commandins.Parameters.AddWithValue("@value", serialized); commandins.ExecuteNonQuery(); } catch (Exception ex) { throw new Exception("Error inserting new row: " + ex.Message); } } else { try { // Existing User We update it string insertString = "update [dbo].[GoogleUser] " + " set [RefreshToken] = @value " + " where username = @key"; SqlCommand commandins = new SqlCommand(insertString, myConnection); commandins.Parameters.AddWithValue("@key", key); commandins.Parameters.AddWithValue("@value", serialized); commandins.ExecuteNonQuery(); } catch (Exception ex) { throw new Exception("Error updating user: " + ex.Message); } } } myConnection.Close(); return TaskEx.Delay(0); } ///  /// Deletes the given key. It deletes the  named file in . ///  /// The key to delete from the data store public Task DeleteAsync(string key) { if (string.IsNullOrEmpty(key)) { throw new ArgumentException("Key MUST have a value"); } SqlConnection myConnection = this.connectdb(); if (!_ConnectionExists) { throw new Exception("Not connected to the database"); } // Deletes the users data. string deleteString = "delete from [dbo].[GoogleUser] " + "where username = @key"; SqlCommand commandins = new SqlCommand(deleteString, myConnection); commandins.Parameters.AddWithValue("@key", key); commandins.ExecuteNonQuery(); myConnection.Close(); return TaskEx.Delay(0); } ///  /// Returns the stored value for the given key or null if the matching file ( /// in  doesn't exist. ///  /// The type to retrieve /// The key to retrieve from the data store /// The stored object public Task GetAsync(string key) { //Key is the user string sent with AuthorizeAsync if (string.IsNullOrEmpty(key)) { throw new ArgumentException("Key MUST have a value"); } TaskCompletionSource tcs = new TaskCompletionSource(); // Note: create a method for opening the connection. SqlConnection myConnection = new SqlConnection(this.ConnectionString); myConnection.Open(); // Try and find the Row in the DB. using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = @username;", myConnection)) { command.Parameters.AddWithValue("@username", key); string RefreshToken = null; SqlDataReader myReader = command.ExecuteReader(); while (myReader.Read()) { RefreshToken = myReader["RefreshToken"].ToString(); } if (RefreshToken == null) { // we don't have a record so we request it of the user. tcs.SetResult(default(T)); } else { try { // we have it we use that. tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize(RefreshToken)); } catch (Exception ex) { tcs.SetException(ex); } } } return tcs.Task; } ///  /// Clears all values in the data store. This method deletes all files in . ///  public Task ClearAsync() { SqlConnection myConnection = this.connectdb(); if (!_ConnectionExists) { throw new Exception("Not connected to the database"); } // Removes all data from the Table. string truncateString = "truncate table [dbo].[GoogleUser] "; SqlCommand commandins = new SqlCommand(truncateString, myConnection); commandins.ExecuteNonQuery(); myConnection.Close(); 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); } //Handel's creating the connection to the database private SqlConnection connectdb() { SqlConnection myConnection = null; try { myConnection = new SqlConnection(this.ConnectionString); try { myConnection.Open(); // ensuring that we are able to make a connection to the database. if (myConnection.State == System.Data.ConnectionState.Open) { _ConnectionExists = true; } else { throw new ArgumentException("Error unable to open connection to the database."); } } catch (Exception ex) { throw new ArgumentException("Error opening Connection to the database: " + ex.Message); } } catch (Exception ex) { throw new ArgumentException("Error creating Database Connection: " + ex.Message); } return myConnection; } } } 

使用class级:

 GoogleOauth g = new GoogleOauth(); AnalyticsService service = g.Handle(userEmailAddress, connectionString, redirectUrl, "YOURAPLICATIONNAME", new[] {AnalyticsService.Scope.AnalyticsReadonly}); DataResource.RealtimeResource.GetRequest request = service.Data.Realtime.Get(String.Format("ga:{0}", profileId), "rt:activeUsers"); RealtimeData feed = request.Execute(); 

如果有人感兴趣,我可以将示例项目上传到github。