インストール

Tsukuyomi OpenID はさまざまなライブラリに依存していますので、Maven によって入手することをおすすめします。

    <repositories>
               :
        <!-- Tsukuyomi Project のリポジトリ -->
        <repository>
            <id>tsukuyomi.sourceforge.jp</id>
            <name>Tsukuyomi Repository</name>
            <url>http://tsukuyomi.sourceforge.jp/maven2</url>
        </repository>
               :
    </repositories>

    <dependencies>
               :
        <dependency>
            <groupId>jp.sourceforge.tsukuyomi.openid</groupId>
            <artifactId>tsukuyomi-openid</artifactId>
            <version>0.2.0</version>
        </dependency>
           :
    </dependencies>

使い方

Tsukuyomi OpenID は Seasar2 と一緒に使用することを推奨しています。そこでまず、app-openid.dicon を以下のように作ります。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd">
<components namespace="openid" >
    <component
        class="jp.sourceforge.tsukuyomi.openid.http.impl.HttpClientManagerImpl" />
    <component
        class="jp.sourceforge.tsukuyomi.openid.rp.impl.RelayPartyConfigImpl">
        <!-- OpenID 認証サーバからの戻り先のパス(サーブレットコンテキスト以降)を指定 -->
        <property name="returnURL">"/login/verify"</property>
    </component>
</components>

また、app.dicon などで openid.dicon を include してください。

つぎに Web アプリケーション側ですが、通常 OpenID を利用する場合は以下の処理をしなければなりません。

  • OpenID の入力を受け付ける
  • 入力された OpenID に対する OpenID Provider(OP) を見つける
  • アソシエーション確立を行う
  • 認証要求を行う(実際には OP の認証ページに移動させる)
  • 認証応答を受け取る
  • 結果の直接検証を行う

Tsukuyomi OpenID では極力省力化を行うためにこのシーケンスをできるだけ単純化し、最少で以下のように3つのメソッド呼び出しだけですむようにしてあります。

  • OpenIDConsumer#findProvider(String) による OP 発見
  • OpenIDConsumer#request() による OP 認証ページへの移動
  • OpenIDConsumer#verify() による結果の直接検証

以下は、Cubby のアクションクラスで用いた例です。このリストを含むサンプルはこちら からダウンロードすることができます。Eclipse 3.3 (Eclipse IDE for Java EE Developers)のプロジェクトとしてインポートが可能です。

package example.action;

import java.util.Map;

import jp.sourceforge.tsukuyomi.openid.OpenIDConsumer;

import org.seasar.cubby.action.Action;
import org.seasar.cubby.action.ActionErrors;
import org.seasar.cubby.action.ActionResult;
import org.seasar.cubby.action.Direct;
import org.seasar.cubby.action.Forward;
import org.seasar.cubby.action.RequestParameter;
import org.seasar.cubby.action.Validation;
import org.seasar.cubby.validator.DefaultValidationRules;
import org.seasar.cubby.validator.ValidationRule;
import org.seasar.cubby.validator.ValidationRules;
import org.seasar.cubby.validator.validators.RequiredValidator;

public class LoginAction extends Action {
    
    private class IdentifierValidator implements ValidationRule {
        public void apply(Map<String, Object[]> params, Object form,
                ActionErrors errors) {
            // findProvider で false が帰ってくると OP が見つけられない、
            // すなわち不正または対応していない OpenID とみなすことができる。
            if (!openIDConsumer.findProvider(openid_identifier)) {
                errors.add("OpenID Identifier が不正です。");
            }
        }
    }

    @RequestParameter
    public String openid_identifier;

    public OpenIDConsumer openIDConsumer;
    
    public ValidationRules validation = new DefaultValidationRules() {
        @Override
        public void initialize() {
            add("openid_identifier", new RequiredValidator());
            add(DATA_CONSTRAINT, new IdentifierValidator());
        }
    };
    
    public String verifiedId;

    @Validation(rules = "validation", errorPage = "main.jsp")
    public ActionResult auth() {
        // 内部で認証サーバに移動させるためのレスポンスを出力している
        openIDConsumer.request();

        // なので戻り値は Direct()
        return new Direct();
    }

    public ActionResult index() {
        // OpenID 入力ページ出力
        return new Forward("main.jsp");
    }

    public ActionResult verify() {
        // 結果の直接検証を行う
        verifiedId = openIDConsumer.verify();

        if (verifiedId == null) {
            // 戻り値が null の場合、検証エラー
            return new Forward("error.jsp");
        }
        
        return new Forward("success.jsp");
    }
}