Примерно год назад я делал небольшой обзор компонента от TMS для работы с Dropbox. Тогда компонент этот был, мягко говоря, «сыроват» и было решено для своих нужд использовать аналогичный компонент от Astonsoft, который на тот момент работал стабильнее и, в принципе, его возможностей вполне хватало. Вполне вероятно, что за год TMS Software улучшило работу своего компонента — я не проверял. Однако оба эти компонента являются платными и не всякий любитель Delphi «потянет» такую сумму на покупку одного компонента. Умолчим про возможности скачать эти и другие компоненты бесплатно. Просто представим, что нам для работы над неким небольшим коммерческим проектом потребовалась очень и очень ограниченная часть возможностей API Dropbox и покупать ради этого компонент — лишние финансовые траты (мы и так вложились «по самое не хочу» в покупку Delphi XE6). Сейчас у нас самая последняя версия Delphi в которой имеется замечательная библиотека REST Client Library с помощью которой можно реализовать работу практически с любым онлайн-сервисом с минимумом затрат (например, с сетью ВКонтакте). Но, как оказалось, не всё так гладко при авторизации по OAuth 2.0 в Dropbox. Рассмотрим работу REST Client Library на двух примерах.
Первый пример — авторизация по OAuth 2.0 в сервисах Google.
В принципе, этот пример я уже приводил, когда только-только знакомился с библиотекой REST Client Library в Delphi XE5.
Создаем в Delphi XE6 новый проект, бросаем на форму компонент OAuth2Authenticator с вкладки «REST Client», делаем двойной клик по компоненту и в открывшемся задаем такие значения параметров:
- Authorization-Endpoint: https://accounts.google.com/o/oauth2/auth
- Token-Endpoint: https://accounts.google.com/o/oauth2/token
- Redirctioon-Endpoint: urn:ietf:wg:oauth:2.0:oob
- Client-ID: значение Client ID вашего проекта
- Client-Secret: значение Client Secret вашего проекта
- Access-Scope: https://www.googleapis.com/auth/drive
- Response-Type: code
(естественно, что перед этим надо создать новое приложение в консоли Google). Должно получиться вот так:
Таким образом, мы пытаемся получить доступ к сервису Google.Диск. Жмем кнопочку «Authorize», в открывшемся окне залогиниваемся в Google, даем разрешение на доступ и в итоге компонент из REST Client Library прекрасно получает и Access Token и Refresh Token о чем свидетельствует следующий скрин:
Как видите — всё элементарно и просто. Теперь можем бросать на форму компоненты RESTClient, RESTRequest, RESTResponse и работать с API.
Теперь попробуем реализовать тоже самое, но только с Dropbox.
Второй пример — авторизация по OAuth 2.0 в Dropbox.
На данный момент Dropbox поддерживает авторизацию как по OAuth 1.0, так и по OAuth 2.0, что не может не радовать. Пробуем авторизоваться по OAuth 2.0. В документации сказано, что можно авторизоваться и без получения промежуточного параметра Code для чего в консоли управления приложением необходимо разрешить использование «implicit grant«:
Ок. Всё включили, Redirect URI задали. Теперь в компоненте OAuth2Authenticator нам необходимо задать такие значения параметров:
- Authorization-Endpoint: https://www.dropbox.com/1/oauth2/authorize
- Token-Endpoint: https://api.dropbox.com/1/oauth2/token
- Redirctioon-Endpoint: http://localhost
- Client-ID: значение App Key вашего проекта
- Client-Secret: значение App Secret вашего проекта
- Access-Scope: не задаем
- Response-Type: token
Проверяем. Жмем кнопку «Authorize» и нас ожидаемо просят ввести свой логин и пароль в Dropbox:
Логинимся, в следующем окне разрешаем доступ к своим данным в Dropbox…и вместо Access Token получаем вот такую «картину маслом»:
Итог — ключа доступа нет, дальнейшая работа с компонентами невозможна. Как быть? Давайте разбираться.
Авторизация по OAuth 2.0. в Dropbox без REST Client Library.
Для начала я решил проверить что вообще происходит в тот момент, когда я разрешаю доступ к моим данным. Так как для работы с OAuth 2.0. нам не требуется составлять и шифровать всякие хитрые параметры как это было в OAuth 1.0, то для такой проверки нам требуется совсем немного компонентов, а именно:
- Webbrowser для отображения страниц
- Memo — для ведения лога работы программы
Бросаем эти компоненты на форму так как вам угодно и читаем документацию по OAuth 2.0 в Dropbox. Прежде всего нам необходимо составить правильный URL. Для того, чтобы сразу получать Access Token наш URL должен иметь вот такую форму:
где client_id — это App Key приложения, а redirect_uri — это заданный нами Redirect URI в Консоли приложения.
Далее из той же документации следует, что если пользователь перейдет в браузере по этому URL, залогинится в сервисе и даст добро на доступ к данным, то в итоге пользователя перенаправят по URL вот такого содержания:
Здесь как раз и содержится то, что нам надо — Access Token. Проверим, как работает этот простой алгоритм авторизации на практике. Задаем несколько констант и пишем такой код на OnShow формы (если не нравится OnShow — пишите где нравится):
const AppKey='какой-то ключ'; RedirectURI = 'http://localhost'; AuthURL = 'https://www.dropbox.com/1/oauth2/authorize?response_type=token&client_id=%s&redirect_uri=%s'; procedure TForm1.FormShow(Sender: TObject); var URL: string; begin URL:=Format(AuthURL,[AppKey,RedirectURI]); WebBrowser1.Navigate2(URL); end;
Теперь, чтобы отслеживать куда нас перенаправляют зададим обработчик события OnBeforeNavigate2 у TWebBrowser:
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject; const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData, Headers: OleVariant; var Cancel: WordBool); begin Memo1.Lines.Add(URL) end;
Запускаем приложение и смотрим что в итоге происходит. А происходит следующее: обработчик срабатывает дважды. Первый раз, как и полагается, перед тем как открыть страницу по URL, который мы сами же и создаем. Здесь все в порядке. Второй раз обработчик срабатывает после того как мы разрешаем доступ к данным в Dropbox, НО вместо ожидаемого перенаправления на http://localhost#что-то-там нас кидает на вот такой замечательный URL:
и именно на этом месте и появляется Error 404 и компонент REST Client Library, естественно, к такому повороту не готов. Как бороться с таким поведением сервиса Dropbox? Решение оказалось довольно простым. Создаем у WebBrowser обработчик события OnNavigationError и пешем там всего одну строку:
procedure TForm1.WebBrowser1NavigateError(ASender: TObject; const pDisp: IDispatch; const URL, Frame, StatusCode: OleVariant; var Cancel: WordBool); begin Cancel:=True; end;
После чего можно смело отлавливать в событии OnNavigateComplete2 URL, содержащий токен доступа. Вот как он будет выглядеть в нашей программе:
Принципиальная проблема решена, а теперь несколько слов непосредственно о REST Client Library. Первое:
Может показаться удивительным, но факт — в мобильном приложении авторизация прошла без проблем. Получал доступ к Dropbox точно также, как и при работе с ВКонтакте — Access Token получен.
Что касается версии для VCL. Форма авторизации находится в модуле REST.Authenticator.OAuth.WebForm.Win. Необходимо самостоятельно определить обработчик события OnNavigateError у Browser так как показано выше, а искать Access Token как и всегда в обработчике события OnAfterRedirect формы авторизации.
Собственно на этом вопрос самостоятельной авторизации по OAuth 2 в Dropbox можно считать закрытым. Теперь можно спокойно авторизовываться и работать с API.
Книжная полка
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
Решил попробовать, действительно есть данная проблема с компонентом, НО, если запустить веб сервер на http://localhost (80 порт) то всё работает отлично, то есть вместо «Redirctioon-Endpoint: http://localhost«, установить любой работающий сервер (только https!), компонент отлично отрабатывает, очевидно в мобильном приложении что то висело на 80 порту.
Да, кстати, про это:
так и есть. В принципе, мне хватает решения из статьи. Тем более что проблему я сумел воспроизвести только на API Dropbox. Со всеми другими API компоненты работают вообще без нареканий :)
А как авторизироватся в Dropbox без использования WebBrowser — все данные вводить в стандартных формах
Использую Lazarus+Synapse
парсить страничку в поисках нужных полей, вставлять значения в поля, обрабатывать клики…долго нудно и, что самое главное, неправильно, т.к. сам по себе протокол OAuth имеет своей целью сделать процесс авторизации пользователя как можно более прозрачным с точке зрения безопасности. А вы получается скрываете от пользователя то, что ему необходимо делать ради его же безопасности хочет он того или нет.
На планшете с андроидом, обратил внимание, что некоторые проги при необходимости обращении к гуглодиску — для авторизации показывают самопальные окна для ввода пароля\логина от гугла — и это довольно неудобно.
А вот некоторые проги умеют показывать окошко в котором показаны текущие зарегистрированные на планшете эккаунты гугла — и ты выбираешь нужный — жмешь подтверждение от гугла — и всё, прога дальше уже имеет доступ к файлам на гуглодиске.
Как вот такое реализовать, доступ к гуглодиску используя уже зарегенный эккаунт от гугла на планшете? В какую сторону смотреть?
За самопальные окна ввода логина и пароля, как по мне, так надо карать ржавым гвоздем. OAuth-авторизация для того и придумана, чтобы НЕ отдавать приложению логин/пароль вообще ни в каком виде — только через браузер с открытой страницей СЕРВИСА.
По поводу Андроида точно не подскажу — надо посмотреть какие разрешения просят такие проги, которые имеют доступ к инфе по аккаунтам и уже от этого отталкиваться в дальнейших поисках…по крайней мере я бы так сделал в отсутствие более полной информации.
Откровенный бред эта OAuth 2.0, так как браузер сам по себе не божественная вещь и всё, что в него может ввести юзер можно и достать. Сама идея в основе гнилая
Здравствуйте
Подскажите, где найти похожие статьи по работе с REST library и Dropbox api
Или здесь объясните, пожалуйста
С этой проблемой вожусь уже месяц, кучу форумов и статей облазил — не получилось все равно
успешно получил токен доступа
Вот пытаюсь составить запрос на скачивание файла (из корневой папки дропбокса)
RESTRequest1.Method := TRestRequestMethod.rmPOST;
RESTClient1.BaseURL := ‘https://content.dropboxapi.com/2/files/download’;
RESTRequest1.Params.AddHeader(‘Authorization’,’Bearer ‘ + OAuth2Authenticator1.AccessToken);
RESTRequest1.Params.AddHeader(‘Dropbox-API-Arg’,'{«path»: «/MyFile.dat»}’);
RESTRequest1.Params.AddItem(‘path’,’/MyFile.dat’,pkGETorPOST,[poDoNotEncode]);
RESTRequest1.Execute;
local_filename := ExtractFilePath(ParamStr(0)) + ‘MyFile.dat’;
SomeStream := tmemorystream.Create;
try
SomeStream.WriteData(RESTResponse1.RawBytes,
length(RESTResponse1.RawBytes));
SomeStream.SaveToFile(local_filename);
finally
SomeStream.Free;
end;
в документации сказано запрос составлять так
https://www.dropbox.com/developers/documentation/http/documentation#files-download
И вроде ничего не упустил
Но выскакивает исключение 400 плохой реквест
Что не так?
Здравствуйте
та же задача… 2 день мучаюсь. скиньте если решение найдено.
Vlad, идея обойти ограничения TOAuth2Authenticator и вручную подготовить URL с параметрами для TWebBrowser мне понравилась. Я попробовал также сделать для аутентификации на сервере ЕСИА. Но URL получается слишком большой. Из-за client_secret содержащего подпись, длина URL больше чем 2083 символа. TWebBrowser такие URL обрезает. Я использую Delphi 10.4.1. На сегодня это последняя версия. Не понимаю, как обойти это ограничение в 2083 символа в URL.
Идея, конечно, как говорил герой одного фильма «завиральная», но может быть этот длинный URL укоротить каким-нибудь сервисом и передать сокращенную ссылку в TWebBrowser?
Подпись, формируемую при помощи КриптоПРО вряд ли можно укоротить. Только одна она, без других параметров в URL, переведённая в base64 занимает более 3800 символов. На стороне сервера ЕСИА её ожидают именно такую. Полагаю, что IE для этого не подходит. А именно он подразумевается в Delphi в качестве движка к TWebBrowser. Я думаю попробовать пойти другим путём. Написать web-приложение на IntraWeb. Там не будет привязки к IE. А в других браузерах нет таких жестких ограничений.