【问题标题】:Google Drive Api - Custom IDataStore with Entity FrameworkGoogle Drive Api - 带有实体框架的自定义 IDataStore
【发布时间】:2020-12-17 02:45:01
【问题描述】:

我实现了我的自定义 IDataStore,以便我可以将 最终用户令牌 存储在我的 数据库 上,而不是保存在 FileSystem 在 %AppData% 内。

public class GoogleIDataStore : IDataStore
{
    ...

    public Task<T> GetAsync<T>(string key)
    {
        TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();

        var user = repository.GetUser(key.Replace("oauth_", ""));

        var credentials = repository.GetCredentials(user.UserId);

        if (key.StartsWith("oauth") || credentials == null)
        {
            tcs.SetResult(default(T));
        }
        else
        {
            var JsonData = Newtonsoft.Json.JsonConvert.SerializeObject(Map(credentials));                
            tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(JsonData));
        }
        return tcs.Task;
    }   
}

控制器

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

    if (result.Credential == null)
        return new RedirectResult(result.RedirectUri);

    var driveService = new DriveService(new BaseClientService.Initializer
    {
        HttpClientInitializer = result.Credential,
        ApplicationName = "My app"
    });

    //Example how to access drive files
    var listReq = driveService.Files.List();
    listReq.Fields = "items/title,items/id,items/createdDate,items/downloadUrl,items/exportLinks";
    var list = listReq.Execute();

    return RedirectToAction("Index", "Home");
}

问题发生在重定向事件上。在第一次重定向之后它工作正常。

我发现重定向事件有所不同。在重定向事件中,T 不是令牌响应,而是一个字符串。此外,密钥以“oauth_”为前缀。

所以我假设我应该在重定向上返回不同的结果,但我不知道要返回什么。

我得到的错误是:Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"State is invalid", Description:"", Uri:""强>

Google 源代码参考 https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.DotNet4/Apis/Util/Store/FileDataStore.cs?r=eb702f917c0e18fc960d077af132d0d83bcd6a88

https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.Auth/OAuth2/Web/AuthWebUtility.cs?r=eb702f917c0e18fc960d077af132d0d83bcd6a88

感谢您的帮助

【问题讨论】:

    标签: c# asp.net-mvc oauth-2.0 google-api google-oauth


    【解决方案1】:

    我不完全确定为什么你的不工作,但这是我使用的代码的副本。完整的课程可以在这里找到DatabaseDatastore.cs

    /// <summary>
            /// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
            /// in <see cref="FolderPath"/> doesn't exist.
            /// </summary>
            /// <typeparam name="T">The type to retrieve</typeparam>
            /// <param name="key">The key to retrieve from the data store</param>
            /// <returns>The stored object</returns>
            public Task<T> GetAsync<T>(string key)
            {
                //Key is the user string sent with AuthorizeAsync
                if (string.IsNullOrEmpty(key))
                {
                    throw new ArgumentException("Key MUST have a value");
                }
                TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
    
    
                // Note: create a method for opening the connection.
                SqlConnection myConnection = new SqlConnection("user id=" + LoginName + ";" +
                                          @"password=" + PassWord + ";server=" + ServerName + ";" +
                                          "Trusted_Connection=yes;" +
                                          "database=" + DatabaseName + "; " +
                                          "connection timeout=30");
                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<T>(RefreshToken));
                        }
                        catch (Exception ex)
                        {
                            tcs.SetException(ex);
                        }
    
                    }
                }
    
                return tcs.Task;
            }
    

    【讨论】:

    • 嗨。我的也在工作。但是在“StoreAsync”之后的初始重定向(为了用户授权访问他们的谷歌驱动器),GetAsync 被调用并且密钥的值 oauth_xxxx@xx.xxx我>。所以这就是我得到的错误。我不确定你的项目是否像我的一样是 MVC ......问题可能与此有关。我将使用Controller 代码编辑我的问题。
    【解决方案2】:

    API 在您的IDataStore 中存储(至少)两个值。从空的 IDataStore 的角度来看,授权过程如下所示(注意哪些行 set 一个值,哪些行 get 一个值):

    Getting IDataStore value:  MyKey       <= null
    
    Setting IDataStore value:  oauth_MyKey => "http://localhost..."
    Setting IDataStore value:  MyKey       => {"access_token":"...
    
    Getting IDataStore value:  oauth_MyKey <= "http://localhost..."
    Getting IDataStore value:  MyKey       <= {"access_token":"...
    

    首先,API 尝试查找已存储的access_token,但数据存储中没有(仅返回null),API 开始授权过程。 “oauth_...”键是 API 在此过程中需要的一些状态信息,通常在检索之前设置(根据我的经验)。

    但是,如果您的 IDataStore 从未收到带有“oauth_..”键的值,因此没有可返回的内容,则只需返回 null,API 应在需要时创建一个新值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多