web-dev-qa-db-ja.com

Google.GData.Client.GDataRequestException-古いコードで認証が突然失敗する

Googleドライブのスプレッドシートを認証してアクセスしようとすると、次の例外が突然発生し始めます。

未処理の例外:Google.GData.Client.GDataRequestException:自動認証要求を実行すると予期しない結果が返されました:Google.GData.Client.Utilities.getAuthException(TokenCollection tokens、Htt pWebResponse response)で404、Google.GData.Client.Utilities.QueryClientLoginToken( Google.GData.Client.GDataGAuthRequest.QueryAuthToken(GDataCredentials gc)at Google.GData.Client.GDataGAuthRequest.EnsureCredentials()at Google.GDataGAuthRequest.EnsureCredentials()でのGDataCredentials gc、サービスserviceName、文字列applicationName、ブールfUseKeepAlive、IWebProxy prox yServer、Uri clientLoginHandler) .Client.GDataRequest.EnsureWebRequest()at Google.GData.Client.GDataGAuthRequest.EnsureWebRequest()at Google.GData.Client.GDataRequest.Execute()at Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter)at Google.GData .Client.GDataGAuthRequest.Execute()at Google.GData.Client.Service.Query(Uri queryUri、DateTime ifModifiedSince、String etag、Int64&contentLength)at Google.GData.Client.Service.Query(FeedQu ery feedQuery)(Google.GData.Documents.DocumentsService.Query(DocumentsListQuery feedQuery)at GoogleLogger.GoogleService.getLastXECLogRows(String folderName、String fileName、Int32 rows)

これは2年間問題なく実行されているコードです。本番システムへのアクセス権限が失われた可能性があると最初に思ったが、Googleドライブは私のWebブラウザに正常にロードされた。他のいくつかのシステムで試してみたところ、まったく同じになりました。

彼らは今日、Google APIで何かを変更しましたか?これは偶然ではありません!

14
Molecool

Googleは以前の認証APIを廃止しました。 OAuth 2.0を代わりに使用する必要があります。

以前のGData APIで新しいAuth APIを使用して、インターネットからあちこちのビットや情報を取得する方法を理解するのに時間がかかりすぎました。時間を節約するために、すべての詳細をスクリーンショットで共有することにしました。

  1. https://console.developers.google.com/project に移動します

  2. Create Projectボタンを押す

enter image description here

  1. プロジェクトを作成します。名前を入力します。

enter image description here

  1. API & Auth> Credentialsに移動し、Create new Client IDボタンを押します。それはあなたのために自動的にJSONキーを作成します-それを無視してください。

enter image description here

  1. ヒットGenerate new P12 key

enter image description here

  1. ファイルのダウンロードが自動的に開始されます。ダウンロードしたファイルを開くにはパスワードが必要です。

enter image description here

  1. ダウンロードしたファイルの名前をKey.p12に変更し、ソリューションに追加します。それに応じてBuild ActionCopy to Output Directoryを設定してください。

enter image description here

  1. Nugetを使用してGoogle API Authをインストールします。パッケージマネージャーコンソールで次のように入力します。

    Install-Package Google.Apis.Auth
    

enter image description here

  1. 手順4で生成されたサービスアカウントのメールアドレスをコピーします。

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();
    
32
Alex Aza

私はこの問題をoAuth2.0のサービスアカウントでこのソリューションを使用して解決しました OAuth 2とサービスアカウントを使用して古いGData API(スプレッドシートAPI)にアクセスする

解決策:1. https://console.developers.google.com/project でプロジェクトとGoogleサービスアカウントを作成します

  1. P12キーを生成します。
  2. 使用するDeveloper ConsoleでAPIを許可します(基本的に古いAPIを使用するため、念のため、この手順をスキップできます)
  3. 以下のコードを使用してください(.NET Framework 4.5!)
  4. また、共有を押して通常のユーザーに権限を付与するので、スプレッドシートドキュメントへのアクセスを「[email protected]」に付与することを忘れないでください。

コード:

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 = "[email protected]";   // 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);
5
Many More

わかりました。次のようにステップバイステップの説明-私が下に提供したコードも参照してください。参考までに、これは.Net 3.5で実行され、以前に提供されたソリューションとは異なり、新しい依存関係はありません。すぐに稼働し始めます。

  1. OAuth 2.0の認証情報をまだ作成していない場合-取得方法はすでに知っていると思いますが、ここにあります。

    a)Google開発者コンソールにログインします。 http://console.developers.google.com b)プロジェクトを作成しますc)認証情報を作成します-「インストールされているアプリケーション」を使用しますd)作成したAPIを追加します必要-Drive APIは間違いなく必要だと思います。念のため、ドライブSDKも追加しました。

  2. 以下のコードをVSにコピーし、最初のMain()メソッドをクライアントキーとシークレットキーで編集します。

  3. アプリを実行し、新しいアクセストークンと更新トークンの両方をコピーします。それらと残りの認証情報を下の2番目のMain()メソッドに入れます。

  4. これで、2番目の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);
    }
  }
}

それがあなたたちのために働くことを願っています-幸運を祈ります!

4
Molecool

Andrew私はgoogle.apis.auth.oauth2 dllをどうやって手に入れたのだろうと思っていました。私はあなたの修正を実行しようとしています、そして私はライブラリをインストールする正しい方法を見つけることができません。

その部分があれば、これを機能させることができるかもしれません。

0
surewould