OAuth с проверкой in.NET


Я пытаюсь создать клиентское приложение на основе .NET (в WPF-хотя на данный момент я просто делаю это как консольное приложение) для интеграции с приложением с поддержкой OAuth, в частности Mendeley (http://dev.mendeley.com), который, по-видимому, использует 3-ногий OAuth.

Это мой первый раз с помощью OAuth, и у меня возникли большие трудности с началом работы с ним. Я нашел несколько библиотек .NET OAuth или помощников, но они кажутся более сложными, чем я думаю необходимость. Все, что я хочу сделать, это иметь возможность выдавать запросы REST API Mendeley и получать ответы обратно!

до сих пор я пробовал:

первый (DotNetOpenAuth) кажется, что он может сделать то, что мне нужно, если я потратил часы и часы, пытаясь понять, как это сделать. Этот во-вторых и в-третьих, насколько я могу судить, не поддерживают коды проверки, которые Менделей отправляет обратно - хотя я могу ошибаться в этом:)

У меня есть ключ потребителя и секрет от Mendeley, и с DotNetOpenAuth мне удалось запустить браузер со страницей Mendeley, предоставляющей проверочный код для пользователя, чтобы войти в приложение. Тем не менее, в этот момент я заблудился и не мог понять, как разумно предоставить это обратно приложение.

Я очень готов признать, что я понятия не имею, с чего начать (хотя кажется, что есть довольно крутая кривая обучения) - если кто-нибудь может указать мне в правильном направлении, я был бы признателен!

1 92

1 ответ:

я с тобой согласен. Классы поддержки OAuth с открытым исходным кодом, доступные для приложений .NET, трудно понять, слишком сложно (сколько методов представлено DotNetOpenAuth?), плохо разработаны (посмотрите на методы с 10 строковыми параметрами в OAuthBase.модуль cs из той ссылки google, которую вы предоставили-нет никакого государственного управления вообще), или иначе неудовлетворительно.

это не должно быть так сложно.

я не эксперт по OAuth, но у меня есть создал класс OAuth client-side manager, который я успешно использую с Twitter и TwitPic. Он относительно прост в использовании. Это с открытым исходным кодом и доступны здесь:Oauth.cs

для обзора, в OAuth 1.0 a...забавно, есть специальное имя, и это похоже на "стандарт", но, насколько я знаю, единственный сервис, который реализует "OAuth 1.0 a", - Это Twitter. Я думаю, что это стандарт достаточно. хорошо, в любом случае в OAuth 1.0 a, как это работает для настольные приложения это:

  1. вы, разработчик приложения, зарегистрировать приложение и получить "ключ" и "секрет". На Арстехнике есть хорошо написанный анализ того, почему эта модель не является лучшей, но, как говорится, это.

  2. ваше приложение работает. При первом запуске он должен заставить пользователя явно предоставить утверждение для приложения, чтобы сделать OAuth-authenticated REST запросы в Twitter и его дочерние службы (например, TwitPic). Для этого необходимо пройти процесс утверждения, включающий явное утверждение пользователем. Это происходит только при первом запуске приложения. Вот так:

    • запрос "маркер запроса". Ака временный токен.
    • откройте веб-страницу, передав этот токен запроса в качестве параметра запроса. Эта веб-страница представляет пользовательский интерфейс для пользователя, спрашивая: "Вы хотите предоставить доступ к этому приложению?"
    • пользователь войдите на веб-страницу twitter и предоставьте или откажите в доступе.
    • появится html-страница ответа. Если пользователь предоставил доступ, есть PIN-код отображается в 48-pt шрифт
    • теперь пользователю нужно вырезать / вставить этот pin-код в поле формы windows и нажать "Далее" или что-то подобное.
    • затем настольное приложение выполняет запрос OAuth-authenticated для "маркера доступа". Еще один запрос на отдых.
    • настольное приложение получает "доступ токен"и" секрет доступа".

после танца утверждения настольное приложение может просто использовать пользовательский "токен доступа" и "секрет доступа" (наряду с пользовательским "ключом потребителя" и "секретом потребителя") для выполнения аутентифицированных запросов от имени пользователя в Twitter. Эти не имеют срока действия, хотя если пользователь де-авторизует приложение, или если в Твиттере почему-то де-авторизует ваше приложение, или если вы потеряете свой маркер доступа и/или секрета, вам нужно повторите танец одобрения.


если вы не умны, поток пользовательского интерфейса может как бы отражать многоступенчатый поток сообщений OAuth. Есть лучший способ.

используйте элемент управления WebBrowser и откройте веб-страницу авторизации в настольном приложении. Когда пользователь нажимает "разрешить", возьмите текст ответа из этого элемента управления WebBrowser, автоматически извлеките PIN-код, а затем получите маркеры доступа. Вы отправляете 5 или 6 HTTP-запросов, но пользователь должен видеть только один разрешить / запретить диалог. Простой.

такой:
alt text


если у вас есть сортировка пользовательского интерфейса, единственной проблемой, которая остается, является создание запросов, подписанных oauth. Это вызывает много людей, потому что требования к подписанию oauth являются своего рода особыми. Это то, что делает упрощенный класс OAuth Manager.

пример кода для запроса токена:

var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;    
oauth.AcquireRequestToken(rtUrl, "POST");

ВОТ И ВСЕ. Простой. Как видно из кода, путь добраться до параметров oauth можно через строковый индексатор, что-то вроде словаря. Метод AcquireRequestToken отправляет запрос, подписанный oauth, на URL-адрес службы, которая предоставляет маркеры запроса, а также временные маркеры. Для Twitter этот URL-адрес является "https://api.twitter.com/oauth/request_token". спецификация oauth говорит, что вам нужно упаковать набор параметров oauth (token, token_secret, nonce, timestamp, consumer_key, version и callback) определенным образом (url-код и объединенный амперсандами) и в лексикографически отсортированном порядке сгенерируйте подпись на этом результате, затем упакуйте те же самые параметры вместе с подписью, сохраненной в новом параметре oauth_signature, по-другому (соединенный запятыми). класс OAuth manager делает это автоматически. он генерирует nonces и временные метки и версии и подписями автоматически - ваше приложение не должно заботиться или быть в курсе этого материала. Просто установите протокол OAuth значения параметров и сделать простой вызов метода. класс manager отправляет запрос и анализирует ответ для вас.

Ок, тогда что? Как только вы получите маркер запроса, вы откроете пользовательский интерфейс веб-браузера, в котором пользователь явно предоставит утверждение. Если вы сделаете это правильно, вы откроете это во встроенном браузере. Для Twitter, URL для этого"https://api.twitter.com/oauth/authorize?oauth_token= " с добавлением oauth_token. Сделайте это в коде вот так:

var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);

(если бы вы делали это во внешнем браузере, вы бы использовали System.Diagnostics.Process.Start(url).)

установка свойства Url приводит к тому, что элемент управления WebBrowser автоматически переходит на эту страницу.

когда пользователь нажимает кнопку "Разрешить" новая страница будет загружена. Это HTML-форма, и она работает так же, как и в полном браузере. В коде зарегистрируйте обработчик для события DocumentedCompleted элемента управления WebBrowser и в этом обработчике возьмите пин-код:

var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter's oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "").Trim();

это немного HTML-скребок экрана.

после захвата pin-кода вам больше не нужен веб-браузер, поэтому:

webBrowser1.Visible = false; // all done with the web UI

...и вы можете также вызвать Dispose () на нем.

следующим шагом является получение маркера доступа, отправив другое сообщение HTTP вместе с этим pin-кодом. Это еще один подписанный вызов oauth, построенный с упорядочением и форматированием oauth, которые я описал выше. Но опять же это очень просто с OAuth.Класс менеджера:

oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
                         "POST",
                         pin);

для Twitter этот URL-адрес"https://api.twitter.com/oauth/access_token".

теперь у вас есть маркеры доступа, и вы можете использовать их в подписанных запросов HTTP. Вот так:

var authzHeader = oauth.GenerateAuthzHeader(url, "POST");

...где url является конечной точкой ресурса. Чтобы обновить статус пользователя, это будет "http://api.twitter.com/1/statuses/update.xml?status=Hello".

затем установите это строка в заголовке HTTP с именем авторизация.

для взаимодействия со сторонними сервисами, такими как TwitPic, вам необходимо построить немного разные заголовок OAuth, например:

var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
                                            "GET",
                                            AUTHENTICATION_REALM);

для Twitter, значения для проверки creds url и realm являются "https://api.twitter.com/1/account/verify_credentials.json", и"http://api.twitter.com/ " соответственно.

...и поставил это строка авторизации в заголовке HTTP называется X-Verify-Credentials-Authorization. Затем отправьте это на свой сервис, например TwitPic, вместе с любым запросом, который вы отправляете.

вот и все.

все вместе, код для обновления статуса twitter может быть что-то вроде этого:

// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control. 
System.Diagnostics.Process.Start(authzUrl);  // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There's been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

OAuth 1.0 a является своего рода сложным под обложками, но использовать его не нужно. Протокол OAuth.Менеджер обрабатывает генерация исходящих запросов oauth, а также получение и обработка содержимого oauth в ответах. Когда запрос Request_token дает вам oauth_token, ваше приложение не должно хранить его. Протокол OAuth.Менеджер достаточно умен, чтобы сделать это автоматически. Аналогично, когда запрос access_token возвращает маркер доступа и секрет, вам не нужно явно хранить их. Протокол OAuth.Менеджер обрабатывает это состояние для вас.

в последующих запусках, когда у вас уже есть маркер доступа и секрет, вы можете создать экземпляр OAuth.Менеджер, как это:

var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;

...а затем создайте заголовки авторизации, как указано выше.

// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);

using (var response = (HttpWebResponse)request.GetResponse())
{
    if (response.StatusCode != HttpStatusCode.OK)
        MessageBox.Show("There's been a problem trying to tweet:" +
                        Environment.NewLine +
                        response.StatusDescription);
}

можно скачать DLL, содержащая OAuth.Класс менеджера здесь. В этой загрузке также есть файл справки. Или вы можете просмотр файла справки в интернете.

см. пример формы Windows, которая использует этот менеджер здесь.


РАБОЧИЙ ПРИМЕР

скачать рабочий пример инструмента командной строки, который использует класс и технику, описанные здесь: