本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

OAuth を使ってソーシャル・ネットワーキング Web サイトにアクセスする: 第 2 回: OAuth 対応のWeb 版 Twitter クライアントを作成する

Xiaobo Yang, Enterprise Java Developer, UK
Xiaobo Yang
Xiaobo Yang はイギリスで働くエンタープライズ Java 開発者です。彼はエンタープライズ情報システム、特にエンタープライズ・ポータルに関心を持っています。Xiaobo は University of Glasgow で航空宇宙工学の博士号を取得しています。

概要: この連載の第 1 回では OAuth プロトコルを紹介し、OAuth 対応のデスクトップ Twitter クライアントを作成する方法を説明しました。第 2 回では、OAuth 対応のWeb 版 Twitter クライアントを作成する方法を学びます。この Twitter クライアントでは、ユーザーが自分の近況をアップデートしたり削除したりすることができ、また友だちのタイムラインを表示することができます。

このシリーズの他の記事を見る

日付:  2010年 1月 26日
レベル:  中級 この記事の原文:  英語
アクティビティー: 7229 ビュー
お気軽にご意見・ご感想をお寄せください: 


この記事を読む前に、サービス・プロバイダー上の保護されたユーザー・リソースにコンシューマー・サイトからアクセスする上で、OAuth が優れた手段であることを理解しておく必要があります。OAuth が優れているのは、OAuth を利用すれば、ユーザーのデータが元々保持されている場所以外のサイトにクレデンシャルが公開されることはないからです。第 1 回で作成したデスクトップ Twitter クライアントを利用すると、Twitter に保持されているユーザー・データへのアクセス権を MyTtDesktopClient に付与することにより、Twitter の近況をアップデートすることができます。同じユーザーが再度アクセスする場合にはアクセス・トークンを再利用できるため、ユーザー・エクスペリエンスが向上されます。

この記事では、OAuth を使用する Web 版の Twitter クライアントを作成する方法を説明します。目標は、Twitter に対するユーザー認証を OAuth を使って行った後でユーザーの近況をアップデートすることができる、Web アプリケーションを作成することです。このアプリケーションは友だちのタイムラインを表示できるようにもする予定であり、優れたマッシュアップ・サイトを構築する際のベースとすることもできます。

Web 版の Twitter クライアントを作成する

MyTtDesktopClient の場合と同じように、この Web 版 Twitter クライアントではユーザーが自分の Twitter の近況をアップデートすることができます。さらに、この Web 版 Twitter クライアントでは、ユーザーの最新の近況を表示したり、ユーザーが自分の近況を削除したりすることもできます。またこの Web アプリケーションでは、OAuth 認証の成功後に Twitter によってリダイレクトされる宛先をコールバック URL として設定することができます。こうするとブラウザーを localhost にリダイレクトできるため、開発の際に非常に便利です。また、OAuth 認証が前回と少し異なることにも注意してください。それは、今回のアプリケーションはデスクトップ・アプリケーションではなくブラウザー・アプリケーションとして登録されるためです。

Web アプリケーション (MyTtWebClient) を Twitter に登録する

今回も前回と同じく、Twitter で OAuth を使う前に、この Web アプリケーションを http://twitter.com/oauth_clients に登録する必要があります。あるいは場合によっては、デスクトップ Twitter クライアントとして登録したアプリケーションを変更することもできます。ここでは新しいアプリケーションを以下のように Twitter に登録します。

  • Application Name (アプリケーション名): MyTtWebClient
  • Description (説明): A Web Twitter client using OAuth (OAuth を使用する Web 版 Twitter クライアント)
  • Application Web site (アプリケーションの Web サイト): ここにアプリケーションのホームページを入力します。
  • Application Type (アプリケーションのタイプ): Browser - ここでは Web アプリケーションを作成します。
  • Callback URL (コールバック URL): ここにアプリケーションのコールバック URL を入力します。localhost では動作しません。
  • Default Access type (デフォルトのアクセス・タイプ): Read & Write - ユーザーが書き込みアクセスできるようにします。
  • Use Twitter for login (ログインに Twitter を使う): Yes - ここでは認証に Twitter を使います。

今回はアプリケーションのタイプが第 1 回の Client とは異なり、Browser であることに注意してください。この場合も Read & Write (読み書き) アクセスを許可することを忘れないでください。また、「Use Twitter for login (ログインに Twitter を使う)」チェックボックスも Yes にチェックを入れます。

アプリケーションを適切に登録できると、コンシューマー・キーコンシューマー・シークレット、そして 3 つの URL (リクエスト・トークンの URLアクセス・トークンの URL承認用の URL) が取得されます。コンシューマー・キーコンシューマー・シークレットWEB-INF/Web.xml の中で設定されます。

MyTtWebClient を作成し、テストする

コードを読まずに Web アプリケーションをコンパイルして実行したい場合には (ソース・コードは下記の「ダウンロード」セクションから入手することができます)、Web.xml の中に皆さんがお持ちのコンシューマー・キーとコンシューマー・シークレットを設定する必要があります。WEB-INF/lib の下に以下のライブラリー・ファイルを追加します。

  • commons-logging-1.1.1.jar
  • log4j-1.2.15.jar
  • twitter4j-2.0.9.jar

ここで、Twitter4J はバージョン 2.0.9 またはそれ以降を使用することに注意してください。その理由は、コールバック URL のカスタマイズがサポートされているのは 2.0.9 バージョンまたはそれ以降の Twitter4J のみだからです。またデフォルトで、コールバック URL は Web.xml の中で構成され、localhost を指します。(Twitter4J は TwitterAPI 用のオープンソースの Java™ ライブラリーです。「参考文献」を参照)。このアプリケーションを MyTtWebClient.war としてコンパイルしてアセンブルし、Tomcat にデプロイし、http://localhost:8080/MyTtWebClient にアクセスしてみます。

MyTtWebClient の中心は MyTwitterServlet というサーブレットです (完全なソース・コードは下記の「ダウンロード」セクションにあります)。このサーブレットは myttWebclient.MyTwitterServlet クラスの中で定義されます。doPost(HttpServletRequest request, HttpServletResponse response) メソッドは、OAuth 認証、ユーザーのTwitter の近況のアップデートと削除、そして友だちのタイムラインの表示を行います。

doPost(...) メソッドは、OAuth 認証、そして login_twitter.htmlupdate_twitter_status.jsp とのさまざまな対話動作を行います。このアプリケーションのウェルカム・ページ (login_twitter.html) はユーザーが Twitter にサインインするためのボタンを表示します (図 1)。ユーザーがこのボタンをクリックすると、doPost(...) メソッドが呼び出されます。ボタンをクリックするユーザーには、新規のユーザー以前に認証されたことがあるユーザーの 2 種類があります。リスト 1 を見るとわかるように、このコードはユーザーの Twitter ID をクッキーからロードしようとします。まだクッキーがロードされていない場合には、そのユーザーは新規のユーザーとして扱われます。Twitter からリクエスト・トークンが要求されると、ユーザーは Twitter にリダイレクトされ、ユーザーの Twitter データに対する読み書きアクセス権をこのコードに付与するための承認が行われます (図 2)。すべてが順調に進むと、Twitter は Web.xml で設定されるコールバック URL にユーザーをリダイレクトするはずです。ここではコールバック URL が MyTtServlet というサーブレットを指すように設定しています。今度は、承認済みのリクエスト・トークンが Twitter によってアクセス・トークンと交換されます。アクセス・トークンが取得できると、そのアクセス・トークンは WEB-INF/token.txt というファイルに保存され、今後のアクセスに使われます。実際のアプリケーションでは、おそらくアクセス・トークンをデータベースに保存するはずです。また、クッキーをユーザーのブラウザーに保存しておき、同じユーザーが再度アクセスした場合のために、以前に認証されたことがあるユーザーからのアクセスかどうかをチェックできるようにするはずです。認証が終わると、ユーザーは update_twitter_status.jsp にリダイレクトされます。サインインに成功した場合のページを示したものが図 3 です。図 3 では、ユーザーの最新の近況アップデートと、そのユーザーの友だちのタイムラインの一部が表示されています。


リスト 1. Twitter で OAuth 認証を行う

protected void doPost(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {
	HttpSession session = request.getSession();

	// Call back from Twitter
	String oauthToken = request.getParameter(PARAM_OAUTH_TOKEN);
	if (oauthToken != null) {
		logger.debug(PARAM_OAUTH_TOKEN + " received from Twitter");
		try {
			Twitter twitter = (Twitter) session.getAttribute(ATTR_TWITTER);
			RequestToken requestToken = (RequestToken) session
					.getAttribute(ATTR_REQUEST_TOKEN);
			AccessToken accessToken;
			if (callbackUrl == null) {
				accessToken = twitter.getOAuthAccessToken(requestToken);
			} else {
				String oauthVerifier = request
						.getParameter(PARAM_OAUTH_VERIFIER);
				logger.debug(PARAM_OAUTH_VERIFIER
						+ " received from Twitter");
				accessToken = twitter.getOAuthAccessToken(requestToken
					.getToken(), requestToken.getTokenSecret(),
					oauthVerifier);
			}
			twitter.setOAuthAccessToken(accessToken);
			session.removeAttribute(ATTR_REQUEST_TOKEN);
			session.setAttribute(ATTR_TWITTER, twitter);

			int id = twitter.verifyCredentials().getId();
			logger.debug("Access token retrieved for user " + id
					+ " from Twitter");
			storeAccessToken(id, accessToken);
			Cookie cookie = new Cookie(COOKIE_TWITTER_ID, "" + id);
			cookie.setMaxAge(63072000); // Valid for 2 years
			response.addCookie(cookie);
			logger.debug("Cookie set for user " + id);

			// Get last status and friends' timelines
			getMyLastStatusAndStoreInSession(session);
			getFriendsTimelinesAndStoreInSession(session);

			// Go to the update status page
			request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(
					request, response);
		} catch (TwitterException e) {
			logger.error("Failed to retrieve access token - "
					+ e.getMessage());
			throw new ServletException(e);
		}
	}

	// Actions within this application
	String action = request.getParameter(PARAM_ACTION);
	if (ACTION_SIGN_IN.equals(action)) {
		logger.debug("Signing in with Twitter...");
		Twitter twitter = new Twitter();
		twitter.setOAuthConsumer(consumerKey, consumerSecret);

		// Try to load Twitter ID from cookies
		String id = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			Cookie cookie;
			for (int i = 0; i < cookies.length; i++) {
				cookie = cookies[i];
				if (COOKIE_TWITTER_ID.equals(cookie.getName())) {
					id = cookie.getValue();
				}
			}
		}

		// Try to load access token if user's Twitter ID is retrieved
		AccessToken accessToken = null;
		if (id != null) {
			accessToken = loadAccessToken(id);
			if (accessToken != null) {
				twitter.setOAuthAccessToken(accessToken);
				session.setAttribute(ATTR_TWITTER, twitter);

				// Get last status and friends' timelines
				try {
					getMyLastStatusAndStoreInSession(session);
					getFriendsTimelinesAndStoreInSession(
						session, true);
				} catch (TwitterException e) {
					e.printStackTrace();
				}

				// Access token loaded, go the up update status page
				logger.debug("Going to the status update page...");
				request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(
						request, response);
			}
		}

		// Can not load access token, go to Twitter for authentication
		if (accessToken == null) {
			try {
				RequestToken requestToken;
				if (callbackUrl == null) {
					requestToken = twitter.getOAuthRequestToken();
				} else {
					requestToken =
						twitter.getOAuthRequestToken(callbackUrl);
				}
				String authorisationUrl = requestToken
						.getAuthorizationURL();
				session.setAttribute(ATTR_TWITTER, twitter);
				session.setAttribute(ATTR_REQUEST_TOKEN, requestToken);

				logger.debug("Redirecting user to " + authorisationUrl);
				response.sendRedirect(authorisationUrl);
			} catch (TwitterException e) {
				logger.error("Sign in with Twitter failed - "
						+ e.getMessage());
				throw new ServletException(e);
			}
		}

	} else if (ACTION_UPDATE.equals(action)) {
	// Handle ACTION_UPDATE, ACTION_DELETE, ACTION_MORE and ACTION_LATEST
	......
}

ユーザーがサインイン・ボタンをクリックした後、MyTwitterServlet がユーザーのクッキーをロードできる場合には、このユーザーは以前に認証されたことがあるユーザーとして扱われます。リスト 1 を見るとわかるように、ユーザーのアクセス・トークンは token.txt から取得しています。従って、このユーザーを再度認証するために Twitter にアクセスする必要はありません。このユーザーの最新の近況と何人かの友だちのタイムラインを Twitter から取得できると、このユーザーは updatee_twitter_status.jsp にリダイレクトされます (図 3)。

この連載の第 1 回MyTtDesktopClient を試した方は、Twitter データへのアクセスを許可した後、Twitter から返された PIN を入力する必要があったことを思い出してください。今回はサーブレットによるリダイレクトを使用できるため、登録の際にアプリケーションのスタイルとして Browser を選択しました。そのため、より適切なユーザー・エクスペリエンスが実現されています。


図 1. MyTtWebClient のウェルカム・ページ
以下の内容が表示された Web ページのスクリーン・ショット。タイトルは「My Twitter Web client (Twitter Web クライアント)」です。テキストが表示されており、その内容は次のとおりです。「This Web site allows you to update your Twitter status without touching your Twitter password. This is done through OAuth. (この Web サイトを利用すると、Twitter のパスワードを入力しなくても Twitter の近況をアップデートすることができます。これは OAuth を使って行われています。)」。そして次に、「Sign in with Twitter (Twitter にサインイン)」というラベルの付いたボタンがあります。

図 2. MyTtWebClient に対してアクセス権を付与する
Twitter ページのスクリーン・ショット。メッセージが表示されており、MyTtWebClient にアクセス権を付与して Twitter データへのアクセスとアップデートを許可するかどうか、承認が要求されています。ユーザー名とパスワードの入力欄には既に入力されています。

図 3. OAuth 認証された後の MyTtWebClient
My Twitter Web Client ページのスクリーン・ショット。画面に表示されているのは、ユーザーの最新の近況アップデートと、新たにアップデートを追加するためのテキスト・フィールド、そして友だちの近況のリストです。

doPost(...) メソッドの残りの部分をリスト 2 に示します。このコード部分は、図 3 に表示されている 3 つのボタンのアクションと、ユーザーの最新のアップデートの最後にある削除リンクに対応しています。これらのボタンやリンクを使うことで、ユーザーは自分の最新のアップデートを削除することや、近況をアップデートすること、そして友だちのタイムラインを見ることができます。このコードを改善する方法としては、例えばこのアプリケーションに GWT (Google Web Toolkit) を使って Ajax を適用し、ユーザー・エクスペリエンスを向上させる方法がありますが、それは皆さんへの宿題とすることにします。図 4 は近況のアップデートが適切に行われた状態を示すスクリーン・ショットです。


リスト 2. myttWebclient.MyTwitterServlet でサポートされているアクション

protected void doPost(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {
	HttpSession session = request.getSession();

	// OAuth authentication support
	......

	} else if (ACTION_UPDATE.equals(action)) {
		logger.debug("Updating Twitter status...");
		String status = request.getParameter(PARAM_STATUS);
		Twitter twitter = (Twitter) session.getAttribute(ATTR_TWITTER);
		try {
			Status twitterStatus = twitter.updateStatus(status);
			logger.debug("Successfully updated the status to ["
					+ twitterStatus.getText() + "].");
			// Update last status
			session.setAttribute(ATTR_LAST_UPDATED_STATUS, twitterStatus
					.getText()
					+ " " + twitterStatus.getCreatedAt());
			session.setAttribute(ATTR_LAST_UPDATED_STATUS_ID, ""
					+ twitterStatus.getId());

			// Update friends' timelines
			getFriendsTimelinesAndStoreInSession(session, true);

			// Stay in the update status page
			logger.debug("Staying in the status update page...");
			request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(
					request, response);
		} catch (TwitterException e) {
			logger.error("Failed to update Twitter status - "
					+ e.getMessage());
			throw new ServletException(e);
		}
	} else if (ACTION_DELETE.equals(action)) {
		logger.debug("Deleting Twitter status...");
		String strId = (String) session
				.getAttribute(ATTR_LAST_UPDATED_STATUS_ID);
		if (strId != null && strId != "") {
			Twitter twitter = (Twitter) session.getAttribute(ATTR_TWITTER);
			try {
				int id = twitter.verifyCredentials().getId();
				twitter.destroyStatus(Long.parseLong(strId));
				session.removeAttribute(ATTR_LAST_UPDATED_STATUS);
				session.removeAttribute(ATTR_LAST_UPDATED_STATUS_ID);
				logger.debug("Last update deleted for Twitter user " + id
						+ " deleted, session record removed");

				// Get last status and friends' timelines
				getMyLastStatusAndStoreInSession(session);
				getFriendsTimelinesAndStoreInSession(session, true);
			} catch (TwitterException e) {
				logger.error("Failed to delete Twitter status - "
						+ e.getMessage());
				throw new ServletException(e);
			}
		}

		// Stay in the update status page
		logger.debug("Staying in the status update page...");
		request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(request,
				response);
	} else if (ACTION_MORE.equals(action)) {
		// Update friends' timelines
		getFriendsTimelinesAndStoreInSession(session);

		// Stay in the update status page
		logger.debug("Staying in the status update page...");
		request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(request,
				response);
	} else if (ACTION_LATEST.equals(action)) {
		// Update friends' latest timelines
		getFriendsTimelinesAndStoreInSession(session, true);

		// Stay in the update status page
		logger.debug("Staying in the status update page...");
		request.getRequestDispatcher(PAGE_UPDATE_STATUS).forward(request,
				response);
	}
}


図 4. MyTtWebClient によってアップデートされた Twitter での近況
ユーザーの最新の近況が実際にアップデートされたことを示す My Twitter Web Client ページのスクリーン・ショット

これで MyTtWebClient の全体像を理解できたことと思います。MyTtWebClient を Web サーバーにデプロイする場合には、コールバックをサポートする必要はありません。コールバックを無効にするためには、単純に WEB-INF/Web.xml の中で callbackUrl パラメーターを空のストリングにします。ただし、OAuth 認証が成功した後のリダイレクト先を Twitter が認識できるように、適切なコールバック URL を Twitter に設定する必要があることを忘れないでください。

この Web アプリケーションを本番環境で使用する場合、Twitter には API の呼び出しに制限があることに注意する必要があります。例えば、REST API 呼び出しに対する回数制限はデフォルトで 1 時間当たり 150 リクエストです。幸いなことに、Twitter では 1 時間当たり 2 万回、リクエストを送信することができます。詳細については Twitter の FAQ を参照してください (「参考文献」を参照)。


まとめ

この連載第 2 回目の今回は、MyTtWebClient という Web 版 Twitter クライアントの作成方法を説明しました。この Web アプリケーションをとおして、OAuth が Web ブラウザーとシームレスに動作することを示しました。また MyTtWebClient には MyTtDesktopClient よりも多くの機能を追加し、例えば最新のアップデートを削除したり友だちのタイムラインを表示したりできるようにしました。第 3 回では、この Web 版 Twitter クライアントを Google App Engine にマイグレートする方法について説明します。



ダウンロード

内容ファイル名サイズダウンロード形式
Source codeoauth-part2-source-code.zip16KBHTTP

ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために

著者について

Xiaobo Yang

Xiaobo Yang はイギリスで働くエンタープライズ Java 開発者です。彼はエンタープライズ情報システム、特にエンタープライズ・ポータルに関心を持っています。Xiaobo は University of Glasgow で航空宇宙工学の博士号を取得しています。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=468961
ArticleTitle=OAuth を使ってソーシャル・ネットワーキング Web サイトにアクセスする: 第 2 回: OAuth 対応のWeb 版 Twitter クライアントを作成する
publish-date=01262010
author1-email=xiaobo.yang@gmail.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。