2013-12-18 87 views
2

我们的应用程序需要让用户同步他们的谷歌日历到我们的内部事件模块,但我坚持做授权并将其存储到我们的数据库。我正在关注这个示例Google OAuth以供参考,但是在该示例中,它声明要实现您自己的使用EF的DataStore,我继续前进并尝试了它,但似乎无法使其工作,并且我一直被困在一对夫妇现在几星期,任何帮助将不胜感激。谢谢!谷歌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

编辑

好的,所以我在过去的几个小时里取得了一些进展,终于能够制作出我自己的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

嗨雨果,我做了,但我用了一个完全不同的方法..使用HttpWebRequest这个网址:https://accounts.google.com/o/oauth2/token而不是他们的.Net库.. – Kevin

回答

0

凯文,这是不清楚什么是不工作..

可能是:

  1. 令牌不被存储在数据库中,在以后的时间

访问用户资源时

  • 认证是没有发生我认为是后者,所以有是您需要解决的两个挑战:

    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

    嗨Peleyal ,那么,我们使用EF,但我们也使用存储库模式和数据依赖注入。所以我想,也许我可以通过我们的存储库的接口,所以我可以将令牌存储在我们的数据库中。我们使用PaaS来托管我们的应用程序,我不确定我们是否可以存储文件,但是我会检查它是否有效。谢谢! – Kevin

    0

    尝试在您的实体框架存储库中存储具有以下参数的对象。

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

    我从其中包含一个实体框架资源库中的Web API获取我的令牌。我检索我的对象作为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; 
        }