Dropbox Java API с проблемами аутентификации GWT

Я использую API Dropbox для Java версии 1.6, который можно найти здесь: https://www.dropbox.com/developers/core/sdks/java

Я также использую GWT 2.5.1 в Eclipse 3.7.

У меня есть следующий код, который работает при запуске в качестве Java-приложения:

    DbxRequestConfig requestConfig = new DbxRequestConfig(type, locale);
    DbxAppInfo appInfo = new DbxAppInfo(APP_ID, APP_SECRET);
    DbxWebAuthNoRedirect webauth = new DbxWebAuthNoRedirect(requestConfig, appInfo);
    String result = webauth.start();
    System.out.println(result);
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String code = reader.readLine();

    webauth = new DbxWebAuthNoRedirect(requestConfig, appInfo);
    DbxAuthFinish finish = webauth.finish(code);

    DbxClient client = new DbxClient(requestConfig, finish.accessToken);
    DbxAccountInfo info = client.getAccountInfo();
    long total = info.quota.total;
    long used = info.quota.normal;

    System.out.println("total: " + total);
    System.out.println("used: " + used);

Это отлично работает, когда я запускаю его как Java-приложение. Однако, когда я пытаюсь сделать что-то подобное с GWT в RemoteServiceServlet. Я получаю исключение, когда пытаюсь сделать

webauth = new DbxWebAuthNoRedirect(requestConfig, appInfo);

Исключение, которое я получаю, следующее:

Caused by: java.lang.ClassCastException: com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection cannot be cast to javax.net.ssl.HttpsURLConnection
at com.dropbox.core.http.StandardHttpRequestor.prepRequest(StandardHttpRequestor.java:160)
at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:87)
at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:21)
at com.dropbox.core.DbxRequestUtil.startPostNoAuth(DbxRequestUtil.java:156)
at com.dropbox.core.DbxRequestUtil.doPostNoAuth(DbxRequestUtil.java:289)
at com.dropbox.core.DbxWebAuthHelper.finish(DbxWebAuthHelper.java:40)
at com.dropbox.core.DbxWebAuthNoRedirect.finish(DbxWebAuthNoRedirect.java:84)
at com.cloudshare.server.DropboxPlayground.getFinish(DropboxPlayground.java:21)
at com.cloudshare.server.DropboxServiceImpl.authenticate(DropboxServiceImpl.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115)
at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:561)
... 40 more

Последние пару часов я бился головой о стену, пытаясь понять, что происходит. Первоначально я хотел использовать DbxWebAuth, но документация в их API включает инструкции с несуществующими классами (я предполагаю, что они когда-то существовали).

Я чувствую, что DbxWebAuthNoRedirect что-то делает, динамически загружая соединение на основе доступных классов. Но я не смог понять это.

Заранее спасибо за помощь!

РЕДАКТИРОВАНИЕ:

Итак, я посмотрел исходный код API Dropbox, и ошибка возникает здесь:

    URL urlObject = new URL(url);
    HttpsURLConnection conn = (HttpsURLConnection) urlObject.openConnection(this.proxy);

Поскольку я использую Google App Engine, он использует свой собственный объект URL, а не объект, импортированный API App Engine. Любые идеи по поводу решения, не связанного с написанием оболочки GWT для API Dropbox.


person Joe    schedule 25.07.2013    source источник
comment
Вы разрабатываете для Google App Engine? Если это так, то класс, указанный в сообщении об ошибке HttpsURLConnection, используемый API-интерфейсом Dropbox, несовместим со способом работы механизма приложения. Если вы не разрабатываете движок приложения, вам нужно отключить движок приложения.   -  person Hilbrand Bouwkamp    schedule 25.07.2013
comment
Я использую ГАЕ. Любые идеи по работе вокруг?   -  person Joe    schedule 25.07.2013
comment
В вашей редакции. GAE внутренне создает коннектор на основе переданного URL-адреса. Однако, поскольку API-интерфейс Dropbox является URL-адресом https, и поэтому API-интерфейс Dropbox ожидает, что будет возвращен класс безопасного соединения, он приводит его к этому классу. Однако GAE поддерживает только http и возвращает небезопасный http-коннектор, который нельзя преобразовать в класс безопасного соединения. Поскольку исходный код API Dropbox находится на github, вы можете попробовать изменить код на незащищенный объект, но я не знаю, сработает ли это. (Кстати, это не проблема GWT, а проблема GAE)   -  person Hilbrand Bouwkamp    schedule 26.07.2013


Ответы (5)


Вы использовали безопасный https:// URL для подключения? Я предполагаю, что если вы используете http://, вы получаете незащищенный коннектор, который нельзя преобразовать в безопасное соединение.

--изменить--

Похоже, что класс HttpsURLConnection просто не поддерживается в GAE, поэтому он не будет работать, в отличие от документации GAE. Использование HttpsURLConnection (проблема с документами). Это означает, что вы, вероятно, не используете его напрямую.

person Hilbrand Bouwkamp    schedule 25.07.2013
comment
К сожалению, у меня нет выбора типа запроса, так как я использую их API. Я просто вызываю метод завершения для экземпляра DbxWebAuthNoRedirect, который может использовать http вместо https. Однако я скептически отношусь к этому, потому что он создает https-сайт для посещения для аутентификации. Возможно, GWT генерирует HTTP-запрос вместо https? Это было бы удивительно, поскольку у меня не было проблем с реализацией API Google Диска с GWT. - person Joe; 26.07.2013
comment
Похоже, что источник Dropbox использует класс URL-адресов Java, который изменен в GAE. Я думаю, что смогу изменить исходный код Dropbox, чтобы решить эту проблему, но я не уверен. Любые идеи? - person Joe; 26.07.2013
comment
Начиная с версии 2.0.5 Dropbox SDK для Java, вы можете использовать GoogleAppEngineHttpRequestor, который явно поддерживает API Fetch URL App Engine. - person Greg; 13.06.2016

Последний Dropbox SDK позволяет вам выбрать реализацию HttpRequestor

new DbxRequestConfig(APP_NAME, userLocale, HttpRequestor);

Так что все, что вам нужно сделать, это адаптировать com.dropbox.core.http.StandardHttpRequestor к Appengine.

Суть: AppengineHttpRequestor.java

person radu-c    schedule 19.09.2013

DbxAppInfo appInfo = new DbxAppInfo(APP_KEY, APP_SECRET);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("107.108.85.10", 80));

StandardHttpRequestor requ = new StandardHttpRequestor(proxy);
DbxRequestConfig config = new DbxRequestConfig("JavaTutorial/1.0",
Locale.getDefault().toString(),requ);
DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(config, appInfo);

Таким образом, использование Proxy (мой брандмауэр) в StandardHttpRequestor и использование этого запрашивающего устройства в DbxRequestConfig у меня сработало.

person Sharad    schedule 31.10.2013

Я тоже столкнулся с той же проблемой. Согласно этому сообщению, https://groups.google.com/forum/#!topic/google-appengine-java/V8pREOXPX24,

com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler 
$Connection extends the class java.net.HttpURLConnection

Поэтому я заменил класс

javax.net.ssl.HttpsURLConnection

by

java.net.HttpURLConnection 

в классе com.dropbox.core.http.StandardHttpRequestor и перестройте Dropbox Java SDK. Он работает нормально. Образец рабочего приложения можно найти по адресу https://gwt-gae-testing.appspot.com/

person user2489475    schedule 24.08.2013

Это единственный способ получить access_token (но я не знаю, как обращаться с другим методом API Dropbox).

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    String code = req.getParameter("code");

    URL fetchurl = new URL(url);
    HTTPRequest request = new HTTPRequest(fetchurl, HTTPMethod.POST);
    String body = "code=" + code + "&grant_type=authorization_code" + "&client_id=" + dropboKey + "&client_secret=" + dropboxSecret + "&redirect_uri=" + redirectUri;
    request.setPayload(body.getBytes("UTF-8"));

    HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);

    String respInJson = new String(response.getContent());

    LOGGER.warning(respInJson);

    JSONObject jsonObj;
    try {
        jsonObj = new JSONObject(respInJson);
        String uid=jsonObj.getString("uid");
        String access_token=jsonObj.getString("access_token");

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}

Я предлагаю изменить HttpRequestor, как сказал @radu-c. Это работает нормально.

person Aerox    schedule 23.05.2014