Google.GData.Client.GDataRequestException - аутентификация неожиданно завершается неудачей в старом коде
При попытке аутентификации и доступа к электронной таблице на диске Google я получаю следующее исключение:
Необработанное исключение: Google.GData.Client.GDataRequestException: Выполнение запроса автоматической подгонки результата: 404 в Google.GData.Client.Utilities.getAuthException(токены TokenCollection, Ответ 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 дс) в Google.GData.Client.GDataGAuthRequest.EnsureCredentials() в Google.GData.Client.GDataRequest.EnsureWebRequest() в Google.GData.Client.GDataGAuthRequest.EnsureWebRequest() в Google.GData.Client.GDataRequest.Execute() в 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 имя_файла, строки Int32)
Это код, который работает в течение двух лет без каких-либо проблем. Сначала я подумал, что у меня могут быть права доступа на мою производственную систему, но Google-накопитель загружается в моем веб-браузере. Пробовал это на нескольких других системах, и я получаю то же самое.
Они что-то изменили в Google API сегодня? Это не может быть совпадением!
Ответы
Ответ 1
Google удалил свой старый API проверки подлинности. Вместо этого следует использовать OAuth 2.0.
Я потратил слишком много времени на то, чтобы выяснить, как использовать новый API Auth с более старым API GData, захватывающим биты и фрагменты информации здесь и там из Интернета.
Я решил поделиться всеми подробностями со скриншотами, чтобы сэкономить ваше время.
![enter image description here]()
- Создать проект. Введите имя.
![enter image description here]()
- Перейдите к
API & Auth
> Credentials
и нажмите кнопку Create new Client ID
. Он автоматически создаст ключ JSON для вас - проигнорируйте это.
![enter image description here]()
- Хит
Generate new P12 key
![enter image description here]()
- Загрузка файла начнется автоматически. Помните пароль, вам нужно будет открыть файл, который вы только что загрузили.
![enter image description here]()
- Переименуйте загруженный файл в Key.p12 и добавьте его в свое решение. Убедитесь, что вы установили соответственно
Build Action
и Copy to Output Directory
.
![enter image description here]()
-
Установите API Google API с помощью Nuget. В консоли диспетчера пакетов введите следующее:
Install-Package Google.Apis.Auth
![enter image description here]()
- Скопируйте адрес электронной почты учетной записи службы, сгенерированный на шаге 4.
![enter image description here]()
-
Предоставьте соответствующее разрешение этому пользователю в Google Таблице.
-
Используйте следующий код для запроса электронной таблицы. Замените адрес электронной почты и адрес электронной таблицы Google в коде ниже.
const string ServiceAccountEmail = "[email protected]ount.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();
Ответ 2
Мне удалось решить эту проблему, используя это решение с учетной записью службы с oAuth2.0
Доступ к старым API-интерфейсам GData (API-интерфейсам таблиц) с использованием OAuth 2 и учетной записи службы
Решение:
1. Создайте учетную запись Project и Google Service в https://console.developers.google.com/project
- Создайте свой ключ p12.
- Разрешить API-интерфейсы в консоли разработчика, которые вы хотите использовать (в основном мы собираемся использовать старый API, поэтому вы можете пропустить этот шаг, но на всякий случай)
- Используйте приведенный ниже код (.NET Framework 4.5!)
- Также не забудьте предоставить "[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);
Ответ 3
Хорошо, я понял это. Пошаговые инструкции следуют ниже: см. Также код, приведенный ниже. FYI, это работает в .Net 3.5 и в отличие от предлагаемого ранее решения нет новых зависимостей. Вы должны быть в рабочем состоянии в кратчайшие сроки.
-
Если вы еще не создали свои учетные данные OAuth 2.0, я предполагаю, что вы уже знаете, как их получить, но здесь:
a) Войдите в консоль разработчика Google: http://console.developers.google.com
б) Создать проект
c) Создайте свои учетные данные - используйте 'установленное приложение'
d) добавьте необходимые API-интерфейсы - я думаю, что API-интерфейс Драйвера определенно требуется. Я также добавил Drive SDK на всякий случай.
-
Скопируйте приведенный ниже код в VS и отредактируйте первый метод Main() с помощью вашего ключа клиента и секретного ключа.
-
Запустите приложение и скопируйте как новый токен доступа, так и токен обновления. Поместите эти и оставшиеся учетные данные во второй метод Main() ниже.
-
Теперь вы сможете запустить второй метод Main() (просто отмените именование). Отныне это будет все, что вам нужно - нет необходимости повторно запускать первый метод Main().
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);
}
}
}
Надеюсь, что это сработает для вас, ребята - удачи!
Ответ 4
Andrew Мне было интересно, как вы получили dll google.apis.auth.oauth2. Я пытаюсь внедрить ваше исправление, и я не могу найти правильный способ установки библиотеки.
Мне кажется, что я смогу заставить это работать после того, как у меня есть эта часть.