Google.GData.Client.GDataRequestException - 旧代码中的身份验证突然失败

时间:2015-05-26 21:16:47

标签: c# google-api gdata google-oauth

尝试在Google云端硬盘上验证和访问电子表格时,我突然开始出现以下异常:

  

未处理的异常:Google.GData.Client.GDataRequestException:   执行aut hentication请求意外返回   结果:404          at Google.GData.Client.Utilities.getAuthException(TokenCollection tokens,   Htt pWebResponse回复)          在Google.GData.Client.Utilities.QueryClientLoginToken(GDataCredentials   gc,S tring serviceName,String applicationName,Boolean   fUseKeepAlive,IWebProxy prox yServer,Uri   clientLoginHandler)          在Google.GData.Client.GDataGAuthRequest.QueryAuthToken(GDataCredentials   GC)          at Google.GData.Client.GDataGAuthRequest.EnsureCredentials()          at Google.GData.Client.GDataRequest.EnsureWebRequest()          at Google.GData.Client.GDataGAuthRequest.EnsureWebRequest()          在Google.GData.Client.GDataRequest.Execute()          at Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)          在Google.GData.Client.GDataGAuthRequest.Execute()          在Google.GData.Client.Service.Query(Uri queryUri,DateTime ifModifiedSince,String etag,Int64& contentLength)          在Google.GData.Client.Service.Query(FeedQuery feedQuery)          在Google.GData.Documents.DocumentsService.Query(DocumentsListQuery   feedQuery)          在GoogleLogger.GoogleService.getLastXECLogRows(String folderName,String fileName,Int32 rows)

这是代码已经运行了两年没有任何问题。我首先想到我可能已经失去了对我的生产系统的访问权限,但谷歌驱动器在我的网络浏览器中加载得很好。在其他几个系统上尝试过它并且得到了相同的结果。

他们今天在Google API中有所改变吗?这不是巧合!

4 个答案:

答案 0 :(得分:33)

Google已停用旧的身份验证API。应该使用OAuth 2.0。

我花了太多时间来弄清楚如何使用较新的Auth API和较旧的GData API从互联网上随处获取信息。 我决定与屏幕截图分享所有细节,以节省您的时间。

  1. 转到https://console.developers.google.com/project

  2. 点击Create Project按钮

  3. enter image description here

    1. 创建项目。输入一些名字。
    2. enter image description here

      1. 转到API & Auth> Credentials并点击Create new Client ID按钮。它会自动为您创建JSON密钥 - 忽略它。
      2. enter image description here

        1. 点击Generate new P12 key
        2. enter image description here

          1. 文件下载将自动开始。记住密码,您需要它才能打开刚刚下载的文件。
          2. enter image description here

            1. 将下载的文件重命名为Key.p12并将其添加到您的解决方案中。请务必相应地设置Build ActionCopy to Output Directory
            2. enter image description here

              1. 使用Nuget安装Google API Auth。在程序包管理器控制台中键入以下内容

                Install-Package Google.Apis.Auth
                
              2. enter image description here

                1. 复制在步骤#4中生成的服务帐户电子邮件地址。
                2. enter image description here

                  1. 在Google电子表格中为此用户授予适当的权限。

                  2. 使用以下代码查询电子表格。在下面的代码中替换电子邮件和Google电子表格URL地址。

                    const string ServiceAccountEmail = "452351479-q41ce1720qd9l94s8847mhc0toao1fed@developer.gserviceaccount.com";
                    
                    var certificate = new X509Certificate2("Key.p12", "notasecret", X509KeyStorageFlags.Exportable);
                    
                    var serviceAccountCredentialInitializer = 
                        new ServiceAccountCredential.Initializer(ServiceAccountEmail)
                        {
                            Scopes = new[] { "https://spreadsheets.google.com/feeds" }
                        }.FromCertificate(certificate);
                    
                    var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
                    
                    if (!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
                        throw new InvalidOperationException("Access token request failed.");
                    
                    var requestFactory = new GDataRequestFactory(null);
                    requestFactory.CustomHeaders.Add("Authorization: Bearer " + credential.Token.AccessToken);
                    
                    var service = new SpreadsheetsService(null) { RequestFactory = requestFactory };
                    
                    var query = new ListQuery("https://spreadsheets.google.com/feeds/list/0ApZkobM61WIrdGRYshh345523VNsLWc/1/private/full");
                    var feed = service.Query(query);
                    
                    var rows = feed.Entries
                        .Cast<ListEntry>()
                        .Select(arg =>
                            new
                            {
                                Field0 = arg.Elements[0].Value,
                                Field1 = arg.Elements[1].Value
                            })
                        .ToList();
                    

答案 1 :(得分:5)

我通过使用带有oAuth2.0的服务帐户的此解决方案设法解决了这个问题 Accessing older GData APIs (Spreadsheet API) using OAuth 2 and a service account

解决方案: 1.在https://console.developers.google.com/project

中创建项目和Google服务帐户
  1. 生成您的p12密钥。
  2. 允许您在开发人员控制台中使用API​​(基本上我们将使用旧的API,因此您可以跳过此步骤,但以防万一)
  3. 使用以下代码(.NET Framework 4.5!)
  4. 也不要忘记授予&#34; youraccount@developer.gserviceaccount.com"通过按Share键为普通用户授予权限,即可访问电子表格文档。
  5. 代码:

    using System.Security.Cryptography.X509Certificates;
    using Google.GData.Client;
    using Google.GData.Extensions;
    using Google.GData.Spreadsheets;
    using Google.Apis.Auth.OAuth2;
    
    string keyFilePath = @"C:\key.p12";    // found in developer console
    string serviceAccountEmail = "youraccount@developer.gserviceaccount.com";   // found in developer console
    var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
    
    ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail) //create credential using certificate
            {
                Scopes = new[] { "https://spreadsheets.google.com/feeds/" } //this scopr is for spreadsheets, check google scope FAQ for others
            }.FromCertificate(certificate));
    
    credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait(); //request token
    
    var requestFactory = new GDataRequestFactory("Some Name"); 
    requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
    
    SpreadsheetsService myService = new SpreadsheetsService("You App Name"); //create your old service
    myService.RequestFactory = requestFactory; //add new request factory to your old service
    
    SpreadsheetQuery query = new SpreadsheetQuery(); //do the job as you done it before
    SpreadsheetFeed feed = myService.Query(query);
    

答案 2 :(得分:4)

好吧,我明白了。分步说明如下 - 另请参阅下面提供的代码。仅供参考,这是在.Net 3.5中运行的,与以前提供的解决方案不同,没有新的依赖关系。你应该立即启动并运行。

  1. 如果您还没有创建OAuth 2.0凭据 - 我假设您已经知道如何获取这些凭据,而不是在这里:

    a)登录您的Google开发者控制台:http://console.developers.google.com b)创建一个项目 c)创建您的凭据 - 使用已安装的应用程序&#39; d)添加您需要的API - 我认为绝对需要Drive API。我还添加了Drive SDK以防万一。

  2. 将以下代码复制到VS中,并使用客户端密钥和密钥编辑第一个Main()方法。

  3. 运行应用并复制新的访问令牌和刷新令牌。将这些和您剩余的凭据放入下面的第二个Main()方法。

  4. 您现在应该能够运行第二个Main()方法(只需反转命名)。从现在开始,这将是你所需要的 - 无需重新运行第一个Main()方法。

  5. BTW,下面的第一个Main()方法可以在这里找到:https://developers.google.com/google-apps/spreadsheets/authorize

    然而,我确实添加了丢失的令牌类型以及访问类型。这些都是必需的,所以请使用下面的代码:

    using System;
    using Google.GData.Client;
    using Google.GData.Spreadsheets;
    using Google.GData.Documents;
    using System.Configuration;
    using System.Collections.Specialized;
    
    namespace GoogleSpreadsheet
    {
      class GoogleOAutho2
      {
    
        private static String folderName = "crazy.ivan";
    
    
        static void Main(string[] args)
        {
          ////////////////////////////////////////////////////////////////////////////
          // STEP 1: Configure how to perform OAuth 2.0
          ////////////////////////////////////////////////////////////////////////////
    
          // TODO: Update the following information with that obtained from
          // https://code.google.com/apis/console. After registering
          // your application, these will be provided for you.
    
          string CLIENT_ID = "your_client_id";
    
          // This is the OAuth 2.0 Client Secret retrieved
          // above.  Be sure to store this value securely.  Leaking this
          // value would enable others to act on behalf of your application!
          string CLIENT_SECRET = "your_secret_key"
    
          // Space separated list of scopes for which to request access.
          string SCOPE = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
    
          // This is the Redirect URI for installed applications.
          // If you are building a web application, you have to set your
          // Redirect URI at https://code.google.com/apis/console.
          string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
    
          string TOKEN_TYPE = "refresh";
    
          ////////////////////////////////////////////////////////////////////////////
          // STEP 2: Set up the OAuth 2.0 object
          ////////////////////////////////////////////////////////////////////////////
    
          // OAuth2Parameters holds all the parameters related to OAuth 2.0.
          OAuth2Parameters parameters = new OAuth2Parameters();
    
          // Set your OAuth 2.0 Client Id (which you can register at
          // https://code.google.com/apis/console).
          parameters.ClientId = CLIENT_ID;
    
          // Set your OAuth 2.0 Client Secret, which can be obtained at
          // https://code.google.com/apis/console.
          parameters.ClientSecret = CLIENT_SECRET;
    
          // Set your Redirect URI, which can be registered at
          // https://code.google.com/apis/console.
          parameters.RedirectUri = REDIRECT_URI;
    
          ////////////////////////////////////////////////////////////////////////////
          // STEP 3: Get the Authorization URL
          ////////////////////////////////////////////////////////////////////////////
    
          // Set the scope for this particular service.
          parameters.Scope = SCOPE;
    
          parameters.AccessType = "offline"; // IMPORTANT and was missing in the original
    
          parameters.TokenType = TOKEN_TYPE; // IMPORTANT and was missing in the original
    
    
          // Get the authorization url.  The user of your application must visit
          // this url in order to authorize with Google.  If you are building a
          // browser-based application, you can redirect the user to the authorization
          // url.
          string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
          Console.WriteLine(authorizationUrl);
          Console.WriteLine("Please visit the URL above to authorize your OAuth "
            + "request token.  Once that is complete, type in your access code to "
            + "continue...");
          parameters.AccessCode = Console.ReadLine();
    
          ////////////////////////////////////////////////////////////////////////////
          // STEP 4: Get the Access Token
          ////////////////////////////////////////////////////////////////////////////
    
          // Once the user authorizes with Google, the request token can be exchanged
          // for a long-lived access token.  If you are building a browser-based
          // application, you should parse the incoming request token from the url and
          // set it in OAuthParameters before calling GetAccessToken().
          OAuthUtil.GetAccessToken(parameters);
          string accessToken = parameters.AccessToken;
          string refreshToken = parameters.RefreshToken;
          Console.WriteLine("OAuth Access Token: " + accessToken + "\n");
          Console.WriteLine("OAuth Refresh Token: " + refreshToken + "\n");
    
          ////////////////////////////////////////////////////////////////////////////
          // STEP 5: Make an OAuth authorized request to Google
          ////////////////////////////////////////////////////////////////////////////
    
          // Initialize the variables needed to make the request
          GOAuth2RequestFactory requestFactory =
              new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
          SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
          service.RequestFactory = requestFactory;
    
          // Make the request to Google
          // See other portions of this guide for code to put here...
    
          // Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
          Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();
    
          // Make a request to the API and get all spreadsheets.
          SpreadsheetFeed feed = service.Query(query);
    
          // Iterate through all of the spreadsheets returned
          foreach (SpreadsheetEntry entry in feed.Entries)
          {
            // Print the title of this spreadsheet to the screen
            Console.WriteLine(entry.Title.Text);
          }
          Console.ReadLine();
    
         }
    
    
        // once you copied your access and refresh tokens
        // then you can run this method directly from now on...
        static void MainX(string[] args)
        {
        GOAuth2RequestFactory requestFactory = RefreshAuthenticate();
    
             SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");  
             service.RequestFactory = requestFactory;
    
          // Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
          Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();
    
          // Make a request to the API and get all spreadsheets.
          SpreadsheetFeed feed = service.Query(query);
    
          // Iterate through all of the spreadsheets returned
          foreach (SpreadsheetEntry entry in feed.Entries)
          {
            // Print the title of this spreadsheet to the screen
            Console.WriteLine(entry.Title.Text);
          }
          Console.ReadLine();
    
    
    
        public static GOAuth2RequestFactory RefreshAuthenticate() {
            OAuth2Parameters parameters = new OAuth2Parameters(){
                RefreshToken = "the_refresh_token_you_copied_from_the_CLI_running_the_first_method";
                AccessToken = "the_access_token_you_copied_from_the_CLI_running_the_first_method";
                ClientId = "your_client_id";
                ClientSecret = "your_dirty_little_secret";
                Scope = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds",
                AccessType = "offline",
                TokenType = "refresh"
            };
            string authUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
            return new GOAuth2RequestFactory(null, "evilspeculator", parameters);
        }
      }
    }
    

    希望对你们有用 - 祝你好运!

答案 3 :(得分:0)

Andrew我想知道你是如何得到google.apis.auth.oauth2 dll的。我试图暗示你的修复,我无法找到安装库的正确方法。

在我有这个部分之后,我觉得我可能能够让它工作。