Google.GData.Client.GDataRequestException – 旧代码中的身份validation突然失败

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

未处理的exception:Google.GData.Client.GDataRequestException:执行aut hentication请求返回意外结果:Google.GData.Client.Utilities.QueryClientLoginToken上的Google.GData.Client.Utilities.getAuthException(TokenCollection tokens,Htt pWebResponse响应)中的404 GDataCredentials gc,S service service,String applicationName,Boolean fUseKeepAlive,IWebProxy prox yServer,Uri clientLoginHandler)at Google.GData.Client.GDataGAuthRequest.QueryAuthToken(GDataCredentials gc)at Google.GData.Client.GDataGAuthRequest.EnsureCredentials()at Google.GData .Client.GDataRequest.EnsureWebRequest()位于Google.GData的Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)上的Google.GData.Client.GDataRequest.Execute()Google.GData.Client.GDataGAuthRequest.EnsureWebRequest() Google.GData.Client.Service.Query(FeedQu)上的.Client.GDataGAuthRequest.Execute()at Google.GData.Client.Service.Query(Uri queryUri,DateTime ifModifiedSince,String etag,Int64&contentLength) 来自GoogleLogger.GoogleService.getLastXECLogRows(String folderName,String fileName,Int32 rows)的Google.GData.Documents.DocumentsService.Query(DocumentsListQuery feedQuery)的ery feedQuery)

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

他们今天在Google API中有什么变化吗? 这不可能是巧合!

谷歌已经退出旧的身份validationAPI。 应该使用OAuth 2.0。

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

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

  2. 点击Create Project按钮

在此处输入图像描述

  1. 创建项目。 输入一些名称。

在此处输入图像描述

  1. 转到API & Auth > Credentials然后单击Create new Client ID按钮。 它会自动为您创建JSON密钥 – 忽略它。

在此处输入图像描述

  1. 点击Generate new P12 key

在此处输入图像描述

  1. 文件下载将自动开始。 记住密码,您需要它来打开刚刚下载的文件。

在此处输入图像描述

  1. 将下载的文件重命名为Key.p12并将其添加到您的解决方案中。 确保相应地设置Build ActionCopy to Output Directory

在此处输入图像描述

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

     Install-Package Google.Apis.Auth 

在此处输入图像描述

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

在此处输入图像描述

  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() .Select(arg => new { Field0 = arg.Elements[0].Value, Field1 = arg.Elements[1].Value }) .ToList(); 

我已经成功解决了这个问题,将此解决方案与服务帐户一起使用oAuth2.0 使用OAuth 2和服务帐户访问旧的GData API(电子表格API)

解决方案:1。在https://console.developers.google.com/project中创建项目和Google服务帐户

  1. 生成您的p12密钥。
  2. 允许您在开发人员控制台中使用API​​(基本上我们将使用旧的API,因此您可以跳过此步骤,但以防万一)
  3. 使用下面的代码(.NET Framework 4.5!)
  4. 另外,在按Share键授予普通用户权限时,不要忘记授予“youraccount@developer.gserviceaccount.com”访问电子表格文档的权限。

码:

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

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

  1. 如果您还没有创建OAuth 2.0凭据 – 我假设您已经知道如何获取这些凭据,但在此处:

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

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

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

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

顺便说一句,下面的第一个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); } } } 

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

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

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