読者です 読者をやめる 読者になる 読者になる

Webサービスを作るってみるその2 OpenIDでmixiと連携

play Java bootstrap OpenID

今回はOpenIDを使用して、mixiとの連携機能を作成します。

Play1系で、しかもJavaで、しかもmixiと連携しようという方はきっと少ないでしょうが。。。。

ちなみに、PlayにはOpenID用のライブラリが標準で用意されてますので楽チンです。


mixiOpenID仕様

オフィシャルはこちら。

単純にmixiにログインしているかどうかだけでなく、マイミクシィ認証とコミュニティ認証という機能があるのが面白いですね。
コミュニティ認証を使って、見られる範囲の制限なんかに使えそうです。(所属しているコミュニティのセッションだけ参加できるとか)


概要

下記を参考に、認証機能を作成していきます。

想定する動作は、

  1. 画面上で [mixiでログイン] のアイコンをクリック。
  2. サーバから mixiの URL へ OpenID を要求する。
  3. mixi からリダイレクトで認証レスポンスの呼び出し。認証に成功していれば OpenID を取得。
  4. OpenID に含まれるmixiのnicknameをセッションに保存する。

※ログインしていない場合は、必ずログイン画面に遷移させる


ログイン画面

まずはログイン画面。

まずはログイン用のボタンをmixi公式から取得して、public以下に配置します。

で、ログイン用のviewを作成。

#{extends 'main.html' /}
#{set title:'ログイン' /}

<div class="container">
<div class="row">
<div class="span8 offset4">
<div id="login">
	<h1>&{'secure.title'}</h1>
		<div class="control-group" >
			#{if flash.error}
				<p class="error">
	    			<div class="control-group error">
		    	        <label class="control-label" for="inputWarning">&{flash.error}</label>
	            	</div>
				</p>
			#{/if}
			#{if flash.success}
				<p class="success">
					&{flash.success}
				</p>
			#{/if}
		<a href="@{Auth.mixi()}">
		<img src="@{'/public/images/login_btn002.png'}" ></a>
	</div>
</div>
</div>
</div>
</div>

ログインボタンにAuth.mixi()へのリンクを作成しただけのViewです。


認証Controllerの作成

認証用のControllerであるAuthを作成します。

package controllers;

import play.libs.OpenID;
import play.libs.OpenID.UserInfo;
import play.mvc.Before;
import play.mvc.Controller;

public class Auth extends Controller {


	@Before(unless = { "login", "mixi", "logout" })
	static void begin() {
		if (!isLoggedIn()) {
			login();
		}
	}

	private static boolean isLoggedIn() {
		return session.contains("username");
	}

	public static void login() {
		render();
	}

	public static void mixi() {
		authenticate("https://mixi.jp");
	}

	private static void authenticate(String url) {
		// 認証完了のレスポンスでなければ OpenID の検証を要求する
		if (!OpenID.isAuthenticationResponse()) {
			OpenID.id(url).required("nickname").verify(); //nicknameも要求する
			return;
		}

		// 認証処理の結果を評価
		UserInfo user = OpenID.getVerifiedID();
		if (user == null) {
			flash.put("error", "認証に失敗しました");
			login();
		} else {

			// 認証完了
			String nickname = user.extensions.get("nickname");

			session.put("username", nickname);
			render("@Application.index");
		}
	}

	public static void logout() {
		session.clear();
		login();
	}
}


ポイントはいくつかありますが、

  • @Beforeでログイン有無を確認(@Withと組み合わせ。後述)
  • OpenID.requiredに"nickname"を指定することで、戻りにニックネームを含めてもらう
  • OpenID.extensions.get("nickname")で、戻りのニックネームを取得

でしょうか。

認証完了の処理はとりあえずニックネームを取得しているだけですが、アプリで管理するユーザーとのひもづけとか、色々やる予定です。



他Controllerとのひもづけ

「※ログインしていない場合は、必ずログイン画面に遷移させる」を実装します。

他のControllerに@Withを使うだけです。

@With(Auth.class)
public class Application extends Controller {


確認

いいですね!


でもこれ、テストどうすればいいんですかね?
mixiのログイン状態に依存するので、すごい難しそうですが。。。。