GAE/JとTwitter4JでTwitterのOAuth

Servletって何?セッションって何?という状態だったので、なかなか大変でした。基本的にTwitter4Jのコードサンプルにある「8. Twitterアカウントによるサインイン」の通りで動きました。

エラー処理が何もないので、実際使うときには親切にメッセージを出さないとユーザが困るはずです。

ハマったところ

  • GWTにしか興味がなかったのでEclipseで「File」→「New」→「Web Application Project」→「Use Google Web Kit」のチェックを外すことをなかなか思いつかなかった。チェックを外すととても単純なテンプレートを作ってくれるので分かりやすい。
  • サンプルにはCallback URL(認証成功後のリダイレクト先)が書かれていて、でもこれはTwitter側で設定してあるから要らないよね?と勝手に書き換えていた。明示的に指定しないと「oauth_verifier」パラメータは付いてこなかった。

war/WEB-INF/web.xml

このファイルにURLとJavaクラスの対応を書きます。以下のように書きました。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
(snip...)
    <servlet>
        <servlet-name>SignInServlet</servlet-name>
        <servlet-class>zenjiro.server.SignInServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>CallBackServlet</servlet-name>
        <servlet-class>zenjiro.server.CallBackServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SignInServlet</servlet-name>
        <url-pattern>/signinservlet</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>CallBackServlet</servlet-name>
        <url-pattern>/callbackservlet</url-pattern>
    </servlet-mapping>
</web-app>

SignInServlet.java

ほとんどサンプルコードのままです。"xxxxxxxx"、"yyyyyyyy"にはそれぞれTwitter側の管理画面で見える「Consumer key」、「Consumer secret」を書きました。

これで、/signinservlet を表示するとTwitterの認証画面にリダイレクトされます。Twitter側で許可すると、/callbackservlet にリダイレクトされます。

package zenjiro.server;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.RequestToken;

public class SignInServlet extends HttpServlet {
    @Override
    protected void doGet(final HttpServletRequest request,
            final HttpServletResponse response) throws ServletException,
            IOException {
        final Twitter twitter = new TwitterFactory()
                .getOAuthAuthorizedInstance("xxxxxxxx", "yyyyyyyy");
        request.getSession().setAttribute("twitter", twitter);
        try {
            final StringBuffer callbackURL = request.getRequestURL();
            final int index = callbackURL.lastIndexOf("/");
            callbackURL.replace(index, callbackURL.length(), "").append(
                    "/callbackservlet");
            final RequestToken requestToken = twitter
                    .getOAuthRequestToken(callbackURL.toString());
            request.getSession().setAttribute("requestToken", requestToken);
            response.sendRedirect(requestToken.getAuthenticationURL());
        } catch (final TwitterException e) {
            throw new ServletException(e);
        }
    }
}

CallBackServlet.java

完全にサンプルコードのままです。Twitterから認証情報つきでリダイレクトされて /callbackservlet が表示された場合は、/ にリダイレクトされます。/ でセッションから"twitter"を取り出すと、認証済みのTwitterインスタンスがもらえます。

package zenjiro.server;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.http.RequestToken;

public class CallBackServlet extends HttpServlet {
    @Override
    protected void doGet(final HttpServletRequest request,
            final HttpServletResponse response) throws ServletException,
            IOException {
        final Twitter twitter = (Twitter) request.getSession().getAttribute(
                "twitter");
        final RequestToken requestToken = (RequestToken) request.getSession()
                .getAttribute("requestToken");
        final String verifier = request.getParameter("oauth_verifier");
        try {
            twitter.getOAuthAccessToken(requestToken, verifier);
            request.getSession().removeAttribute("requestToken");
        } catch (final TwitterException e) {
            throw new ServletException(e);
        }
        response.sendRedirect(request.getContextPath() + "/");
    }
}

/での処理

GWTを使っているときにはセッションからTwitterインスタンスを取り出すのにサーバサイド側で以下のような書き方をします。

final Twitter twitter = (Twitter) getThreadLocalRequest()
        .getSession().getAttribute("twitter");

試しに twitter.getMentions() でmentionを取得すると、それらしいものが返ってきました。

認証情報の永続化

これだと、Webブラウザを一旦閉じると、また認証画面を通らないといけないので、認証情報をどこかに永続化する必要があります。そもそもあらったー的なサービスならcronで動かす必要がありますし。

が、まだDataStoreの使い方が分からないのでそれは後日。

広告

“GAE/JとTwitter4JでTwitterのOAuth” への1件の返信

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中