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

Mol*_*ool 15 c# google-api gdata google-oauth

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

未处理的异常: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位于Google.GData的Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)的Google.GData.Client.GDataRequest.Execute()的Google.GData.Client.GDataGAuthRequest.EnsureWebRequest()上的.Client.GDataRequest.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中有所改变吗?这不可能是巧合!

Ale*_*Aza 33

谷歌已经退出旧的身份验证API.应该使用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
    
    Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

  • @AlexAza非常感谢这次演练.这正是我需要使用OAread 2.0和Spreadsheets API,尽管有些屏幕自您发布以来略有改变.关于步骤#10的一点澄清 - 需要许可的"此用户"是服务帐户电子邮件地址.在与该电子邮件共享电子表格之前,我收到了403 Forbidden错误. (3认同)

小智 5

我已经成功解决了这个问题,将此解决方案与服务帐户一起使用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);
Run Code Online (Sandbox Code Playgroud)