当前位置: 首页 > 知识库问答 >
问题:

使用存储令牌从C#Windows服务访问DriveService-INVALID_GRANT异常

汪鸿志
2023-03-14

这是我第一次使用谷歌的驱动器api,所以如果我做错了什么,我提前道歉。

以下是我得到的:

我使用一个web应用程序手动遍历OAuth2舞蹈,以便在TokenResponse中获得AccessToken、RefreshToken和TokenType。那些值都成功地回来了,我存储了它们。

//Populate the token response with the stored values
_tokenResponse = new TokenResponse
{
    AccessToken = AppConfiguration.GetSetting("StoredAccessToken"),
    TokenType = AppConfiguration.GetSetting("StoredTokenType"),
    RefreshToken = AppConfiguration.GetSetting("StoredRefreshToken"),
    Issued = DateTime.Parse(AppConfiguration.GetSetting("StoredTokenIssuedDate")),
    ExpiresInSeconds = long.Parse(AppConfiguration.GetSetting("StoredExpiresInSeconds"))
};

//Next, build our code flow
_apiCodeFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
    {
        ClientSecrets = new ClientSecrets
            {
                ClientId = AppConfiguration.GetSetting("ApiClientId"),
                ClientSecret = AppConfiguration.GetSetting("ApiClientSecret")
            },
        Scopes = new[] { DriveService.Scope.Drive },
        DataStore = new FileDataStore(AppConfiguration.GetSetting("RegisteredApplicationName"))
    });
//Now create the UserCredential with those stored values        
_credential = new UserCredential(_apiCodeFlow, AppConfiguration.GetSetting("DriveApiServiceAccountEmail"), _tokenResponse);
//And generate a DriveService instance using the UserCredential
_driveService = new DriveService(new BaseClientService.Initializer
{
    HttpClientInitializer = _credential,
    ApplicationName = AppConfiguration.GetSetting("RegisteredApplicationName")
});
DriveService.Files.List.Execute()
"Error:\"invalid_grant\", Description:\"\", Uri:\"\""

现在,我已经深入谷歌文档好几天了,几乎不知所措。我开始研究他们提供的DrEdit解决方案,但它引用了在他们最近的API名称空间中看不到的对象,如:IAuthorizationState、NativeApplicationClient。我正在使用google.apis.drive.v2、google.apis.auth.oauth2、google.apis.auth.oauth2.flows、google.apis.oauth2.responses、google.apis.util和google.apis.util.store名称空间。我是不是漏掉了什么?

我想知道这是否与请求来自的url有关,因为你必须在谷歌控制台注册这些应用程序的所有重定向url。但是,我没有办法指定从windows服务执行此操作时要使用的重定向url。不过,这可能不是问题,只是一个想法。

我的需求相当简单--我只需要能够使用我保存的刷新令牌,以及仅为此目的创建的新用户的用户名,并获得一个DriveService实例,该实例将允许我遍历该用户可以访问的文件。

任何帮助都将真诚地感谢。提前感谢!!

在GoogleAuthorizationCodeFlow类中,有一个名为“RefreshTokenAsync”的方法,它接受用户名、刷新令牌和取消令牌。它在Fiddler中产生的结果与调用DriveService类中的任何方法相同,因此我认为它在调用DriveService时会自动尝试在幕后刷新令牌。不确定这是否对那些可能能够回答这个问题的人有帮助,但我想我无论如何都要提到。

我创建了自己的IDataStore实现,下面是GetAsync方法的代码,我已经逐步完成了该方法,它返回了一个标记对象:

    public Task<T> GetAsync<T>(string key)
    {
        TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
        try
        {
            //First, load the token from our local json file
            //NOTE: If using the built in FileDataStore, Google would store this same json info in the local users appdata\roaming\{appname} folder
            Stream stream = new FileStream("StoredToken.json", FileMode.Open, FileAccess.Read);
            //Read the file contents into a string
            string sToken = (new StreamReader(stream)).ReadToEnd();
            //Close the stream so that the file isn't locked
            stream.Close();
            stream.Dispose();
            //Deserialize into the type that Google requests
            var token = Google.Apis.Json.NewtonsoftJsonSerializer.Instance.Deserialize<T>(sToken);
            //Set the result of the TaskCompletionSource to our value
            tcs.SetResult(token);
        }
        catch (Exception exc)
        {
            //No need to throw exception here - whatever is calling this method would want to handle exceptions.  
            //So, just set the Exception of the TaskCompletionSource and return it
            tcs.SetException(exc);
        }

        return tcs.Task;
    }
        _credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            clientSecrets: new ClientSecrets
                {
                    ClientId = AppConfiguration.GetSetting("ApiClientId"),
                    ClientSecret = AppConfiguration.GetSetting("ApiClientSecret")
                },
            scopes: new[] {DriveService.Scope.Drive},
            dataStore: new CustomTokenDataStore(),
            user: AppConfiguration.GetSetting("DriveApiServiceAccountEmail"),
            taskCancellationToken: CancellationToken.None).Result;

        _driveService = new DriveService(new BaseClientService.Initializer
        {
            HttpClientInitializer = _credential,
            ApplicationName = AppConfiguration.GetSetting("RegisteredApplicationName")
        });
            using (GoogleDriveApiUtils util = new GoogleDriveApiUtils())
            {
                FilesResource.ListRequest request = util.DriveService.Files.List();

                /*Documentation for using the search parameters:
                 * https://developers.google.com/drive/search-parameters
                 */

                //Add this to the query to get only folders
                request.Q = "mimeType='application/vnd.google-apps.folder'";
                
                FileList fList = request.Execute();
            }

还有别的想法吗?再次感谢所有的帮助:)

共有1个答案

蓬弘
2023-03-14

FileDataStore将信息存储在%appdata%中,并从中获取信息。要使用存储的数据,您需要对iDataStore进行自己的隐含,然后可以发送FileDataStore的insted,这也是iDataStore的另一个隐含。

这只是从我的GoogleAnalytics代码中复制过来的,您只需将其更改到您的作用域中,一旦您创建了自己的iDatastore()隐式,它就可以工作了;

IDataStore StoredRefreshToken = new myDataStore();
// Oauth2 Autentication.
using (var stream = new System.IO.FileStream("client_secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
 credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
 GoogleClientSecrets.Load(stream).Secrets,
 new[] { AnalyticsService.Scope.AnalyticsReadonly },
 "user", CancellationToken.None, StoredRefreshToken).Result;
}

您可以在http://daimto.com/google-oauth2-csharp/#loading_stored_refresh-token找到一个基本示例

 类似资料:
  • 是否可以使用serviceaccount令牌获得k8s群集访问权限? 我的脚本没有访问kubeconfig文件的权限,但是,它可以访问/var/run/secrets/kubernetes处的服务帐户令牌。io/serviceaccount/token。 以下是我尝试过的步骤,但不起作用。 kubectl配置设置凭据sa用户--令牌=$(cat/var/run/secrets/kubernetes

  • 我无法获得足够的权限来使用我的应用程序访问Azure Key Vault(而不是通过用户登录)。以下是我的设置: 我已经给了我的名为“keyvault”的应用程序所有的许可。 我的应用程序注册了Azure Active Directory。我已经允许它进入密钥库:

  • 我找到的签名Google云存储Blob的示例和源代码都需要服务帐户凭据文件(私钥是特定的)。例如: https://cloud.google.com/storage/docs/access-control/signing-urls-with-helpers#storage-签名url获取对象python 但是,由于我遵循此处讨论的授权流程,因此我只有OAuth2.0访问令牌(并且我没有能够访问GC

  • 问题内容: 是否有人从Oracle存储过程成功访问了Web服务?如果是这样,那是Java存储过程吗?PL / SQL存储过程? 有什么原因为什么我不应该尝试从存储的proc访问WS? 这是我到目前为止发现的几个参考 数据库Web服务 从Java存储过程调用外部Web服务 为了澄清,这是针对SOAP调用的 问题答案: 首先,您要调用哪种Web服务?我假设是SOAP或REST。 对于REST Web服

  • 我试图使用Windows Azure开发多层云应用程序。为了存储数据,我选择了Azure存储表和Azure存储Blob。 我的应用程序的不同层使用同一组功能,但方式不同。e、 g.他们都必须能接触斑点。我决定使用单类库来访问Windows Azure Blob存储,但我遇到了一个400错误。 当我直接从工作者角色连接到blob时,它工作正常,但当我从类库调用类时,它失败,状态代码为400(请求错误

  • 在Mule EE 3.8.5中,当加载oauth2访问令牌时,我得到了ClassCastException。我使用的是mule-module-security-oauth2-provider版本1.7.2和mule-module-objectstore 2.1.0 stracktraces开始: 我的配置将令牌成功存储到一个简单的 H2 数据库表中,格式为: 创建一个表ACCESSTOKENOBJ