API Google GData Docs .NET с OAuth 2.0, возвращающим 401 - PullRequest
1 голос
/ 14 октября 2011

В настоящее время я пишу приложение .NET WPF, которое использует API Документов и Календаря Google. Я планирую интегрировать некоторые из более новых API, например, Tasks, на более позднем этапе, поэтому я хочу начать использовать OAuth 2.0 сейчас в процессе подготовки. Мне удалось получить и сохранить токен обновления и доступа, и я реализовал некоторую логику для получения дополнительных токенов доступа по истечении срока действия текущих. Однако у меня много проблем с загрузкой документа в Google Docs. Кажется, что клиентские библиотеки GData изначально не поддерживают OAuth 2.0, и я не хочу переходить к более новым клиентским библиотекам (например, для задач), потому что на этом этапе я не хочу зависеть от DotNetOpenAuth. Вместо этого я реализовал свой собственный OAuth2Authenticator, который добавляет необходимый заголовок OAuth 2, и я использую это с GData ResumableUploader. Когда я пытаюсь отправить запрос на загрузку документа с помощью ResumableUploader, я получаю 401 Несанкционированный ответ с сообщением Token Invalid - Invalid AuthSub token.

Я звоню вот так:

ResumableUploader ru = new ResumableUploader(512);

Document entry = new Document();
entry.Title = documentName;
entry.MediaSource = new MediaFileSource(localDocumentPath, "application/pdf");
entry.Type = Document.DocumentType.PDF;

Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
link.Rel = ResumableUploader.CreateMediaRelation;
entry.DocumentEntry.Links.Add(link);

ru.Insert(new OAuth2Authenticator("MyApplicationName", "MyAccessToken"), entry.DocumentEntry);

Что приводит к этому запросу (от Fiddler):

POST https://docs.google.com/feeds/upload/create-session/default/private/full
HTTP/1.1 Authorization: OAuth sOmeTThing+SomThNig+etc==
Slug: DOC_0108.pdf
X-Upload-Content-Type: application/pdf
X-Upload-Content-Length: 175268
GData-Version: 3.0
Host: docs.google.com
Content-Type: application/atom+xml; charset=UTF-8
Content-Length: 508 Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
 xmlns:gd="http://schemas.google.com/g/2005"
 xmlns:docs="http://schemas.google.com/docs/2007">
   <title type="text">DOC_0108.pdf</title>
   <link href="https://docs.google.com/feeds/upload/create-session/default/private/full"
    rel="http://schemas.google.com/g/2005#resumable-create-media" />  
   <category term="http://schemas.google.com/docs/2007#pdf"
    scheme="http://schemas.google.com/g/2005#kind" label="pdf" />
</entry>

И связанный 401 ответ:

HTTP/1.1 401 Unauthorized
Server: HTTP Upload Server Built on Sep 27 2011 04:44:57 (1317123897)
WWW-Authenticate: AuthSub realm="http://www.google.com/accounts/AuthSubRequest"
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Date: Thu, 13 Oct 2011 08:45:11 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate

Token invalid - Invalid AuthSub token.

Я пробовал в заголовках как «Authorization: OAuth», так и «Authorization: Bearer», поскольку документация по API и OAuth 2.0 кажется разделенной, и я также пытался добавить токен в виде строки запроса (? Access_token = и? oauth_token =) но все эти вещи дают одинаковый ответ.

Я прошел через все вопросы по API Google и OAuth, сообщения в блогах, документацию, которую я могу найти, и попробовал многочисленные способы выполнения этого вызова (несколько реализаций с .NET GData API, REST-клиентский пакет NuGet, мой собственный REST реализация клиента и т. д.) и я не могу обойти эту проблему.

Любая помощь будет наиболее ценной.

1 Ответ

0 голосов
/ 22 октября 2011

Я могу получать и создавать документы с помощью OAuth. После проверки подлинности в Google для доступа к области документов я делаю следующее:

// get the list of available google docs
        RequestSettings settings = new RequestSettings(kApplicationName);
        settings.AutoPaging = false;
        if (settings != null)
        {
            DocumentsRequest request = new DocumentsRequest(settings);
            request.Service.RequestFactory = GetGoogleOAuthFactory();
            Feed<Document> feed = request.GetEverything();

            List<Document> all = new List<Document>(feed.Entries);

            // loop through the documents and add them from google
            foreach (Document entry in all)
            {
                // first check to see whether the document has already been selected or not
                bool found = model.Docs.Any(d => d.GoogleDocID == entry.ResourceId);
                if (!found)
                {
                    GoogleDocItem doc = new GoogleDocItem();
                    doc.GoogleDocID = entry.ResourceId;
                    doc.ETag = entry.ETag;

                    doc.Url = entry.DocumentEntry.AlternateUri.Content;
                    doc.Title = entry.Title;
                    doc.DocType = entry.Type.ToString();
                    doc.DocTypeID = entry.Type;

                    if (entry.ParentFolders.Count == 0)
                    {
                        // add the doc to the list
                        model.AvailableDocs.Add(doc);

                        // if the doc is a folder, get the children
                        if (doc.DocTypeID == Document.DocumentType.Folder)
                        {
                            AddAllChildrenToFolder(ref doc, entry, all);
                        }
                    }
                }
            }
        }

public GOAuthRequestFactory GetGoogleOAuthFactory()
    {
        // build the base parameters
        OAuthParameters parameters = new OAuthParameters
        {
            ConsumerKey = kConsumerKey,
            ConsumerSecret = kConsumerSecret
        };

        // check to see if we have saved tokens and set
        var tokens = (from a in context.GO_GoogleAuthorizeTokens select a);
        if (tokens.Count() > 0)
        {
            GO_GoogleAuthorizeToken token = tokens.First();
            parameters.Token = token.Token;
            parameters.TokenSecret = token.TokenSecret;
        }

        // now build the factory
        return new GOAuthRequestFactory("anyname", kApplicationName, parameters);
    }

Я разместил свой образец авторизации здесь: .net - Google / OAuth 2 - Автоматический вход . DocumentsRequest из бинарных файлов .NET от Google. Хотя я еще не создал новый документ с этим, я использую аналогичные классы для создания элементов календаря.

...