7

Trong ứng dụng của tôi, tôi đang sử dụng Google API V 3.0. Thư viện Net với Google OAuth2 để đồng bộ hóa lịch biểu và lịch biểu của Google. Tôi đang sử dụng mã dưới đây để lấy đối tượng dịch vụ Google.Apis.Calendar.v3.CalendarService. Trong quá trình xác thực, tôi đã lưu trữ tệp Json và từ đó tôi đang yêu cầu đối tượng Google.Apis.Auth.OAuth2.UserCredential.Cách Google API V 3.0. Thư viện Net và Google OAuth2 Xử lý mã thông báo làm mới

private Google.Apis.Auth.OAuth2.UserCredential GetGoogleOAuthCredential() 
{ 
    GoogleTokenModel _TokenData = new GoogleTokenModel(); 
    String JsonFilelocation = "jsonFileLocation; 
    Google.Apis.Auth.OAuth2.UserCredential credential = null; 
    using (var stream = new FileStream(JsonFilelocation, FileMode.Open, 
        FileAccess.Read)) 
    { 
     Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.Folder = "Tasks.Auth.Store"; 
     credential = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
     Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(stream).Secrets, 
     new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar }, 
     "user", 
     CancellationToken.None, 
     new FileDataStore("OGSync.Auth.Store")).Result; 
    } 
    return credential; 
} 

Yêu cầu đối với mã đối tượng dịch vụ là:

Google.Apis.Calendar.v3.CalendarService _V3calendarService = new Google.Apis.Calendar.v3.CalendarService(new Google.Apis.Services.BaseClientService.Initializer() 
{ 
HttpClientInitializer = GetGoogleOAuthCredential(), 
ApplicationName = "TestApplication", 
}); 

Trên đang hoạt động tốt để có được những đối tượng Calendarservice. Câu hỏi của tôi là, tệp Json của tôi có mã thông báo làm mới và truy cập. cách mã trên xử lý mã thông báo làm mới để có được dịch vụ khi mã thông báo truy cập hết hạn? Bởi vì tôi cần phải gọi đối tượng Calendarservice thường xuyên, tôi thích triển khai thực hiện mẫu đơn cho đối tượng calenderService. Cách nhận Calendarservice mà không cần gọi điện cho GetGoogleOAuthCredential thường xuyên? Bất kỳ trợ giúp/hướng dẫn nào được đánh giá cao.

+0

Ngoài ra kiểm tra http://stackoverflow.com/a/24972426/833846 –

Trả lời

2

Đó là số lượng lớn của thư viện khách hàng! phép thuật này được thực hiện tự động cho bạn :)

UserCredential triển khai cả IHttpExecuteInterceptor và IHttpUnsuccessfulResponseHandler. vì vậy bất cứ khi nào mã thông báo truy cập sẽ hết hạn, hoặc đã hết hạn, máy khách sẽ thực hiện cuộc gọi đến máy chủ ủy quyền để làm mới mã thông báo và nhận mã thông báo truy cập mới (có giá trị trong 60 phút tiếp theo).

đọc thêm về nó tại https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#credentials

+0

ok cảm ơn, sau đó mỗi khi tôi cần dịch vụ tôi có cần gọi máy chủ ủy quyền không. là có cách nào để kiểm tra mã thông báo cho dù đó là hết hạn hay không và thực hiện cuộc gọi máy chủ nếu cần thiết? –

+0

Thư viện thực hiện điều đó cho bạn. – peleyal

+0

UserCredential sẽ không làm mới mã thông báo khi sử dụng ứng dụng khách IMAP. có thể nó sẽ khi sử dụng đối tượng dịch vụ Google API, nhưng không phải trong mọi trường hợp. – skyfree

1

Đối với tôi, thư viện khách hàng không thực hiện làm mới, thậm chí không tạo được dấu hiệu làm mới.
Tôi kiểm tra xem mã thông báo đã hết hạn chưa và làm mới. (Mã thông báo có thời gian sử dụng 1 giờ). credential.Token.IsExpired sẽ cho bạn biết liệu nó đã hết hạn chưa, credential.Token.RefreshToken (userid) sẽ làm mới mã thông báo cần thiết.

12

Đã dành hai ngày cuối cùng để tự tìm hiểu điều này. Thư viện không tự động làm mới mã thông báo trừ khi bạn chỉ định "access_type = offline".

https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth

Tôi sẽ dán mã Tôi đang sử dụng và nếu có bất cứ điều gì bạn không hiểu, chỉ cần hỏi. Tôi đã đọc rất nhiều bài viết và tôi litteraly đã làm việc này ngay bây giờ để có một số mã nhận xét và nó đã không được refactored được nêu ra. Tôi hy vọng điều này sẽ giúp một ai đó. Các gói NuGet tôi đang sử dụng là:

Google.Apis.Auth.MVC

Google.Apis.Calendar.v3

Code:

AuthCallbackController:

[AuthorizationCodeActionFilter] 
public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController 
{ 
protected static readonly ILogger Logger = ApplicationContext.Logger.ForType<AuthCallbackController>(); 

/// <summary>Gets the authorization code flow.</summary> 
protected IAuthorizationCodeFlow Flow { get { return FlowData.Flow; } } 

/// <summary> 
/// Gets the user identifier. Potential logic is to use session variables to retrieve that information. 
/// </summary> 
protected string UserId { get { return FlowData.GetUserId(this); } } 

/// <summary> 
/// The authorization callback which receives an authorization code which contains an error or a code. 
/// If a code is available the method exchange the coed with an access token and redirect back to the original 
/// page which initialized the auth process (using the state parameter). 
/// <para> 
/// The current timeout is set to 10 seconds. You can change the default behavior by setting 
/// <see cref="System.Web.Mvc.AsyncTimeoutAttribute"/> with a different value on your controller. 
/// </para> 
/// </summary> 
/// <param name="authorizationCode">Authorization code response which contains the code or an error.</param> 
/// <param name="taskCancellationToken">Cancellation token to cancel operation.</param> 
/// <returns> 
/// Redirect action to the state parameter or <see cref="OnTokenError"/> in case of an error. 
/// </returns> 
[AsyncTimeout(60000)] 
public async override Task<ActionResult> IndexAsync(AuthorizationCodeResponseUrl authorizationCode, 
    CancellationToken taskCancellationToken) 
{ 
    if (string.IsNullOrEmpty(authorizationCode.Code)) 
    { 
     var errorResponse = new TokenErrorResponse(authorizationCode); 
     Logger.Info("Received an error. The response is: {0}", errorResponse); 
     Debug.WriteLine("Received an error. The response is: {0}", errorResponse); 
     return OnTokenError(errorResponse); 
    } 

    Logger.Debug("Received \"{0}\" code", authorizationCode.Code); 
    Debug.WriteLine("Received \"{0}\" code", authorizationCode.Code); 


    var returnUrl = Request.Url.ToString(); 
    returnUrl = returnUrl.Substring(0, returnUrl.IndexOf("?")); 

    var token = await Flow.ExchangeCodeForTokenAsync(UserId, authorizationCode.Code, returnUrl, 
     taskCancellationToken).ConfigureAwait(false); 

    // Extract the right state. 
    var oauthState = await AuthWebUtility.ExtracRedirectFromState(Flow.DataStore, UserId, 
     authorizationCode.State).ConfigureAwait(false); 

    return new RedirectResult(oauthState); 
} 

protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData 
{ 
    get { return new AppFlowMetadata(); } 
} 

protected override ActionResult OnTokenError(TokenErrorResponse errorResponse) 
{ 
    throw new TokenResponseException(errorResponse); 
} 


//public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController 
//{ 
// protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData 
// { 
//  get { return new AppFlowMetadata(); } 
// } 
//} 

}

Phương pháp điều khiển gọi Google API

public async Task<ActionResult> GoogleCalendarAsync(CancellationToken cancellationToken) 
    { 
     var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()). 
      AuthorizeAsync(cancellationToken); 

     if (result.Credential != null) 
     { 
      //var ttt = await result.Credential.RevokeTokenAsync(cancellationToken); 

      //bool x = await result.Credential.RefreshTokenAsync(cancellationToken); 

      var service = new CalendarService(new BaseClientService.Initializer() 
      { 
       HttpClientInitializer = result.Credential, 
       ApplicationName = "GoogleApplication", 
      }); 
      var t = service.Calendars; 

      var tt = service.CalendarList.List(); 

      // Define parameters of request. 
      EventsResource.ListRequest request = service.Events.List("primary"); 
      request.TimeMin = DateTime.Now; 
      request.ShowDeleted = false; 
      request.SingleEvents = true; 
      request.MaxResults = 10; 
      request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime; 

      // List events. 
      Events events = request.Execute(); 
      Debug.WriteLine("Upcoming events:"); 
      if (events.Items != null && events.Items.Count > 0) 
      { 
       foreach (var eventItem in events.Items) 
       { 
        string when = eventItem.Start.DateTime.ToString(); 
        if (String.IsNullOrEmpty(when)) 
        { 
         when = eventItem.Start.Date; 
        } 
        Debug.WriteLine("{0} ({1})", eventItem.Summary, when); 
       } 
      } 
      else 
      { 
       Debug.WriteLine("No upcoming events found."); 
      } 


      //Event myEvent = new Event 
      //{ 
      // Summary = "Appointment", 
      // Location = "Somewhere", 
      // Start = new EventDateTime() 
      //  { 
      //   DateTime = new DateTime(2014, 6, 2, 10, 0, 0), 
      //   TimeZone = "America/Los_Angeles" 
      //  }, 
      // End = new EventDateTime() 
      //  { 
      //   DateTime = new DateTime(2014, 6, 2, 10, 30, 0), 
      //   TimeZone = "America/Los_Angeles" 
      //  }, 
      // Recurrence = new String[] { 
      //  "RRULE:FREQ=WEEKLY;BYDAY=MO" 
      //  }, 
      // Attendees = new List<EventAttendee>() 
      //  { 
      //  new EventAttendee() { Email = "[email protected]" } 
      //  } 
      //}; 

      //Event recurringEvent = service.Events.Insert(myEvent, "primary").Execute(); 

      return View(); 
     } 
     else 
     { 
      return new RedirectResult(result.RedirectUri); 
     } 
    } 

nguồn gốc lớp FlowMetadata

public class AppFlowMetadata : FlowMetadata 
    { 
     //static readonly string server = ConfigurationManager.AppSettings["DatabaseServer"]; 
     //static readonly string serverUser = ConfigurationManager.AppSettings["DatabaseUser"]; 
     //static readonly string serverPassword = ConfigurationManager.AppSettings["DatabaseUserPassword"]; 
     //static readonly string serverDatabase = ConfigurationManager.AppSettings["DatabaseName"]; 
    ////new FileDataStore("Daimto.GoogleCalendar.Auth.Store") 
    ////new FileDataStore("Drive.Api.Auth.Store") 
    //static DatabaseDataStore databaseDataStore = new DatabaseDataStore(server, serverUser, serverPassword, serverDatabase); 


    private static readonly IAuthorizationCodeFlow flow = 
new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer 
{ 
    ClientSecrets = new ClientSecrets 
    { 
     ClientId = "yourClientId", 
     ClientSecret = "yourClientSecret" 

    }, 
    Scopes = new[] 
    { 
CalendarService.Scope.Calendar, // Manage your calendars 
//CalendarService.Scope.CalendarReadonly // View your Calendars 
    }, 
    DataStore = new EFDataStore(), 
}); 

    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(); 

     //var store = new UserStore<ApplicationUser>(new ApplicationDbContext()); 
     //var manager = new UserManager<ApplicationUser>(store); 
     //var currentUser = manager.FindById(controller.User.Identity.GetUserId()); 

     return controller.User.Identity.GetUserId(); 

    } 

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

    public override string AuthCallback 
    { 
     get { return @"/GoogleApplication/AuthCallback/IndexAsync"; } 
    } 
} 

Entity framework 6 lớp DataStore

public class EFDataStore : IDataStore 
    { 
     public async Task ClearAsync() 
     { 
      using (var context = new ApplicationDbContext()) 
      { 
       var objectContext = ((IObjectContextAdapter)context).ObjectContext; 
       await objectContext.ExecuteStoreCommandAsync("TRUNCATE TABLE [Items]"); 
      } 
     } 

     public async Task DeleteAsync<T>(string key) 
     { 
      if (string.IsNullOrEmpty(key)) 
      { 
       throw new ArgumentException("Key MUST have a value"); 
      } 

     using (var context = new ApplicationDbContext()) 
     { 
      var generatedKey = GenerateStoredKey(key, typeof(T)); 
      var item = context.GoogleAuthItems.FirstOrDefault(x => x.Key == generatedKey); 
      if (item != null) 
      { 
       context.GoogleAuthItems.Remove(item); 
       await context.SaveChangesAsync(); 
      } 
     } 
    } 

    public Task<T> GetAsync<T>(string key) 
    { 
     if (string.IsNullOrEmpty(key)) 
     { 
      throw new ArgumentException("Key MUST have a value"); 
     } 

     using (var context = new ApplicationDbContext()) 
     { 
      var generatedKey = GenerateStoredKey(key, typeof(T)); 
      var item = context.GoogleAuthItems.FirstOrDefault(x => x.Key == generatedKey); 
      T value = item == null ? default(T) : JsonConvert.DeserializeObject<T>(item.Value); 
      return Task.FromResult<T>(value); 
     } 
    } 

    public async Task StoreAsync<T>(string key, T value) 
    { 
     if (string.IsNullOrEmpty(key)) 
     { 
      throw new ArgumentException("Key MUST have a value"); 
     } 

     using (var context = new ApplicationDbContext()) 
     { 
      var generatedKey = GenerateStoredKey(key, typeof(T)); 
      string json = JsonConvert.SerializeObject(value); 

      var item = await context.GoogleAuthItems.SingleOrDefaultAsync(x => x.Key == generatedKey); 

      if (item == null) 
      { 
       context.GoogleAuthItems.Add(new GoogleAuthItem { Key = generatedKey, Value = json }); 
      } 
      else 
      { 
       item.Value = json; 
      } 

      await context.SaveChangesAsync(); 
     } 
    } 

    private static string GenerateStoredKey(string key, Type t) 
    { 
     return string.Format("{0}-{1}", t.FullName, key); 
    } 
} 

nguồn gốc lớp cho GoogleAuthorizationCodeFlow. Bật mã thông báo làm mới tồn tại lâu dài giúp tự động "làm mới" mã thông báo, điều này đơn giản nghĩa là nhận mã thông báo truy cập mới.

https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth

internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow 
{ 
    public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base (initializer) { } 

    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri) 
    { 
     return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl)) 
     { 
      ClientId = ClientSecrets.ClientId, 
      Scope = string.Join(" ", Scopes), 
      RedirectUri = redirectUri, 
      AccessType = "offline", 
      ApprovalPrompt = "force" 
     }; 
    } 
} 

GoogleAuthItem được sử dụng với EFDataStore

public class GoogleAuthItem 
{ 
    [Key] 
    [MaxLength(100)] 
    public string Key { get; set; } 

    [MaxLength(500)] 
    public string Value { get; set; } 
} 

public DbSet<GoogleAuthItem> GoogleAuthItems { get; set; } 
+0

Cảm ơn bạn đã chia sẻ, có vẻ như cách giải quyết lớn (Y) –

+0

Đồng thời kiểm tra http://stackoverflow.com/a/24972426/833846 –

Các vấn đề liên quan