2013-12-18 2 views
2

Наше приложение должно позволить пользователям синхронизировать календарь Google с нашим внутренним модулем событий, но я застрял на авторизации и сохранил его в нашей БД. Я следовал этому образцу Google OAuth для справки, но в этом примере было заявлено о внедрении собственного DataStore, который использует EF, я пошел и попробовал, но я не могу заставить его работать, и я застрял на пару недель, любая помощь будет принята с благодарностью. Благодаря!Google OAuth Хранилище данных для токенов

У меня было что-то вроде этого раньше:

public class TokenDataStore : IDataStore 
{ 
    private readonly IUnitOfWork _unitOfWork; 
    private readonly IUserRepository _userRepository; 
    private readonly IBusinessRepository _businessRepository; 

    public TokenDataStore(IUnitOfWork unitOfWork, IUserRepository userRepository, IBusinessRepository businessRepository) 
    { 
     this._unitOfWork = unitOfWork; 
     this._userRepository = userRepository; 
     this._businessRepository = businessRepository; 
    } 

    //Todo: Add IdataStore Members 

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

Некоторые больше информации: - MVC 4 -.Net 4,5 - EF 5 - API для Google

EDIT

Хорошо, поэтому я сделал некоторый прогресс за последние пару часов, я, наконец, смог сделать свой собственный AppFlowMetaData

private readonly IAuthorizationCodeFlow flow; 
    private readonly GoogleAPI _API; 
    private readonly IGoogleAPIRepository _googleAPIRepository; 
    private readonly IUnitOfWork _unitOfWork; 

    public AppFlowMetadata(GoogleAPI API, IGoogleAPIRepository googleAPIRepository, IUnitOfWork unitOfWork) 
    { 
     this._API = API; 
     this._googleAPIRepository = googleAPIRepository; 
     this._unitOfWork = unitOfWork; 

     this.flow = 
     new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer 
     { 
      ClientSecrets = new ClientSecrets 
      { 
       ClientId = ConfigurationManager.AppSettings["GP_Key"], 
       ClientSecret = ConfigurationManager.AppSettings["GP_Secret"] 
      }, 
      Scopes = new[] { CalendarService.Scope.Calendar }, 
      DataStore = new TokenDataStore(_API, _googleAPIRepository, _unitOfWork) 
     }); 
    } 

также мой собственный магазин данных класс:

private readonly IGoogleAPIRepository _googleAPIRepository; 
    private readonly IUnitOfWork _unitOfWork; 
    private readonly GoogleAPI _model; 

    public TokenDataStore(GoogleAPI model, IGoogleAPIRepository googleAPIRepository, IUnitOfWork unitOfWork) 
    { 
     this._googleAPIRepository = googleAPIRepository; 
     this._unitOfWork = unitOfWork; 
     this._model = model; 
    } 

Теперь я сталкиваюсь с проблемой во время обратного вызова. Поэтому, когда пользователь подписывается с использованием своей учетной записи, в моем классе хранилища данных я сохраняю токен в виде строки в базе данных, и когда код попадает в ту часть, где я получаю токен из моей модели, передаваемый тип данных является строкой а не обычный ответ токена. Вот полный код для моего хранилища данных:

public class TokenDataStore : IDataStore 
{ 
    private readonly IGoogleAPIRepository _googleAPIRepository; 
    private readonly IUnitOfWork _unitOfWork; 
    private readonly GoogleAPI _model; 

    public TokenDataStore(GoogleAPI model, IGoogleAPIRepository googleAPIRepository, IUnitOfWork unitOfWork) 
    { 
     this._googleAPIRepository = googleAPIRepository; 
     this._unitOfWork = unitOfWork; 
     this._model = model; 
    } 

    public System.Threading.Tasks.Task StoreAsync<T>(string key, T value) 
    { 
     var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value); 
     if(serialized.Contains("access_token")) 
     { 
      _model.TokenString = serialized; 

      _googleAPIRepository.Save(_model, EntityState.Modified); 
      _unitOfWork.Commit(); 
     } 
     return TaskEx.Delay(0); 
    } 

    public System.Threading.Tasks.Task DeleteAsync<T>(string key) 
    { 
     _model.TokenString = ""; 

     _googleAPIRepository.Save(_model, EntityState.Modified); 
     _unitOfWork.Commit(); 

     return TaskEx.Delay(0); 
    } 

    public Task<T> GetAsync<T>(string key) 
    { 
     TaskCompletionSource<T> tcs = new TaskCompletionSource<T>(); 
     try 
     { 
      tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(_model.TokenString)); 
     } 
     catch(Exception ex) 
     { 
      tcs.SetException(ex); 
     } 

     return tcs.Task; 
    } 

    public System.Threading.Tasks.Task ClearAsync() 
    { 
     return TaskEx.Delay(0); 
    } 
} 
+0

Вы смогли это сделать в конце? Я застрял в том же сценарии. Большое спасибо –

+1

Привет, Hugo, я сделал, но я использовал совершенно другой подход. Используя HttpWebRequest для этого URL: https: //accounts.google.com/o/oauth2/token, а не их .Net Library .. – Kevin

ответ

0

Kevin, непонятно, что не работает ..

Может быть:

  1. токены не хранятся в базе данных
  2. аутентификации не происходит при доступе пользователей ресурсов на более позднее время

Я предполагаю, что это последнее, так что это две проблемы, которые необходимо исправить:

  1. Срок действия токена делает базу данных недействительной
  2. токены не подается обратно в googleauthenticator при доступе пользователей ресурсов

Что вам нужно сделать, которые, чтобы обеспечить вам разрешить доступ в автономном режиме, так что сервер имеет доступ к ресурсам, пока пользователь не присутствует или сеанс вне сферы действия. Здесь прочитайте главу «автономный доступ»: Using oAuth for WebApplications

Убедитесь, что вы подтверждаете, что токены все еще действительны при подаче их обратно в аутентификатор. Если нет, вам нужно использовать токен обновления, чтобы обновить аутентификацию. Validating token

Вам необходимо будет убедиться, что googleauthenticator вызывается с помощью токенов из базы данных, чтобы обеспечить доступ к вашему коду.

Надеюсь, я принял правильную проблему ...;)

0

Вы можете использовать FileDataStore (https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.DotNet4/Apis/Util/Store/FileDataStore.cs), который хранит свои данные в файлах и не EntityFramework.

Что касается вашего вопроса - я не понял, какая у вас проблема? Вам нужно больше информации о том, как вводить данные в объект потока? Или вы помогаете с EF? ... Просьба предоставить дополнительную информацию.

+0

Hi Peleyal , Ну, мы используем EF, но мы также используем шаблон репозитория и инъекцию зависимостей данных. Поэтому я подумал, может быть, я могу просто передать интерфейс нашего репозитория, чтобы я мог хранить токен в нашей БД. Мы находимся на PaaS для размещения нашего приложения, я не уверен, можем ли мы хранить файлы, но я проверю, работает ли это. Благодаря! – Kevin

0

Попробуйте сохранить объект со следующими параметрами в репозитории Entity Framework.

public string access_token { get; set; } 
    public string token_type { get; set; } 
    public long? expires_in { get; set; } 
    public string refresh_token { get; set; } 
    public string Issued { get; set; } 

Я извлекаю свои токены из веб-Api, который содержит репозиторий Framework Entity Framework. Я извлекаю свой объект как строку JSON. Используйте Google.Api.Json.NewtonsoftJsonSerializer для десериализации строки Json.

public Task<T> GetAsync<T>(string key) 
    { 
     TaskCompletionSource<T> tcs = new TaskCompletionSource<T>(); 
     try 
     { 
      string dataStoreView = this.httpClient.Get(uri).ResponseBody; 

      tcs.SetResult(Google.Apis.Json.NewtonsoftJsonSerializer.Instance.Deserialize<T>(dataStoreView)); 
     } 
     catch (Exception ex) 
     { 
      tcs.SetException(ex); 
     } 

     return tcs.Task; 
    } 
Смежные вопросы