OpenIG自習室(第6回:代理認証 Lv.3)

takaです。

前回はテキストファイルからアカウント情報を取得する代理認証を行いました。

今回は、データベースからアカウント情報を取得して代理認証を行ってみます。
実際の環境ではデータベースサーバとOpenIGサーバは別運用であるのが望ましいですが、テストなのでOpenIGサーバ上にデータベースを構築します。

検証作業は、以下の環境で実施しています。

OS :Ubuntu 12.04 LTS
CPU:Intel Celeron 2.20GHz
MEM:2GB

アプリケーションサーバ:target.example.com(192.168.0.10)
OpenIGサーバ             :gateway.example.com(192.168.0.20)
データベースサーバ :gateway.example.com(192.168.0.20)


1. データベースの準備

ここではデータベースとしてMySQLを使います。

1-1. MySQLのインストール
インストール方法は特に記載しませんので、ご利用環境に合わせてデータベースをセットアップしてください。

1-2. データベース作成
テスト用のデータベースを作成します。
データベース名は example としています。

mysql> CREATE DATABASE example;
Query OK, 1 row affected (0.07 sec)

作成したデータベースに切り替えます。

mysql> USE example;
Database changed

1-3. テーブル作成
テスト用のテーブルを作成します。
テーブル名は users としています。
なお、fullname は必須ではありません。

mysql> CREATE TABLE users (
    -> username varchar(50),
    -> password varchar(50),
    -> fullname varchar(50),
    -> email varchar(255)
    -> );
Query OK, 0 rows affected (0.16 sec)

作成したテーブルを確認します。

mysql> SHOW COLUMNS FROM users;
4 rows in set (0.00 sec)

1-4. データ追加
テスト用のデータを作成します。
email の値は、config.json で記載したメールアドレスにしてください。

mysql> INSERT INTO users VALUES ('foo','bar','Foo Bar','foo@example.com');
Query OK, 1 row affected (0.10 sec)

2. Webアプリケーションコンテナの設定

この検証作業ではTomcatを使っていますので、TomcatからMySQLに接続するための設定が必要です。

2-1. JNDI設定
TomcatからMySQLに接続するためのJNDI設定を行います。
リソース名(ここでは forgerock)は任意で結構です。
{MySQL User Name}、{MySQL User Password}、{Database Name}はそれぞれご利用環境に合わせて記述してください。

# vi $TOMCAT_HOME/conf/context.xml

<Resource name="jdbc/forgerock" auth="Container" type="javax.sql.DataSource"
 maxActive="100" maxIdle="30" maxWait="10000"
 username="{MySQL User Name}" password="{MySQL User Password}" driverClassName="com.mysql.jdbc.Driver"
 url="jdbc:mysql://localhost:3306/{Database Name}"/>
# vi $TOMCAT_HOME/conf/web.xml

<resource-ref>
    <description>MySQL Connection</description>
    <res-ref-name>jdbc/forgerock</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

2-2. MySQL Connector/J のインストール
JavaからMySQLを扱うためのJDBCドライバをインストールします。
こちらよりドライバをダウンロードして解凍します。
現在(2013年8月)の最新バージョンは 5.1.25 です。

解凍後は、$TOMCAT_HOME/lib にコピーします。
ubuntu の場合、/usr/share/java 以下にコピーし、/usr/share/tomcat6/lib に mysql-connector-java.jar という名前でシンボリックリンクを張りました。

3. config.json ファイルの変更

ForgeRock社が提供するサンプルのコンフィグファイルに含まれる WordPressLoginSQL.json を参考に、ファイルを修正します。

【WordPress】
WordPressを使っている場合は、ご利用環境に合わせて WordPressLoginSQL.json の以下の箇所を修正してください。

9行 :baseURI のURL
18行:condition のパス
40行:dataSource のデータソースパス
42行:parameters のEメールアドレス
50行:uri のURL
55行:redirect_to のURL

【簡易認証アプリ】
簡易認証アプリケーションを使う方は、第5回で使った config.json を以下のようにカスタマイズします。

a. LoginChain の変更
第5回で追加した FileAttributesFilter を、“SqlAttributesFilter” に変更します。

{
    "name": "LoginChain",
    "type": "Chain",
    "config": {
        "filters": ["SqlAttributesFilter","LoginRequestFilter" ],
        "handler": "ClientHandler"
    }
},

b. SqlAttributesFilter の追加
LoginChainとLoginRequestFilterの間に、SqlAttributesFilter の記述を追加します。
(FileAttributesFilter はそのまま記述していても影響ありません)
なお、dataSource のリソース名は、JNDI設定で指定した値と同じにしてください。

{
    "name": "SqlAttributesFilter",
    "type": "SqlAttributesFilter",
    "config": {
        "target":"${exchange.credentials}",
        "dataSource": "java:comp/env/jdbc/forgerock",
        "preparedStatement":"SELECT username, password FROM users WHERE email = ?;",
        "parameters": ["foo@example.com"]
    }
},

これで config.json の変更は完了です。

参考までに、簡易認証アプリ用のconfig.jsonを全文掲載しておきます。

{
    "heap": {
        "objects": [
            {
                "name": "HandlerServlet",
                "type": "HandlerServlet",
                "config": {
                    "handler": "DispatchHandler",
                    "baseURI": "http://192.168.0.10:80"
                }
            },
            {
                "name": "DispatchHandler",
                "type": "DispatchHandler",
                "config": {
                    "bindings": [
                        {
                            "condition": "${exchange.request.uri.path == '/sample/login.php'}",
                            "handler": "LoginChain",
                        },
                        {
                            "handler": "ClientHandler",
                        }
                    ]
                }
            },
            {
                "name": "LoginChain",
                "type": "Chain",
                "config": {
                    "filters": ["SqlAttributesFilter","LoginRequestFilter" ],
                    "handler": "ClientHandler"
                }
            },
            {
                "name": "SqlAttributesFilter",
                "type": "SqlAttributesFilter",
                "config": {
                      "target":"${exchange.credentials}",
                      "dataSource": "java:comp/env/jdbc/forgerock",
                      "preparedStatement":"SELECT username, password FROM users WHERE email = ?;",
                      "parameters": ["foo@example.com"]
                }
            },
            {
                "name": "LoginRequestFilter",
                "type": "StaticRequestFilter",
                "config": {
                    "method": "POST",
                    "uri": "http://192.168.0.10:80/sample/login.php",
                    "form": {
                        "userid": ["${exchange.credentials.username}"],
                        "password": ["${exchange.credentials.password}"],
                        "action": ["login"]
                    }
                }
            }, 
            {
                "name": "ClientHandler",
                "type": "ClientHandler",
                "config": {
                }
            }
        ]
    },
    "servletObject": "HandlerServlet",
}

4. 動作テスト

コンフィグファイルを変更したので、OpenIGが稼働するWebアプリケーションコンテナを再起動します。
Webブラウザでターゲットアプリケーションを閲覧し、自動でログインできていることを確認しましょう。

もしもログインできない場合、config.json ファイルの記述、データベース接続設定などを見直してみてください。
また、第4回でご紹介したキャプチャーログを取得してみると、アカウント情報が正常にPOSTされているかどうかが一目でわかります。

さて、うまくいきましたでしょうか?
アカウント情報を外部ファイルから取得する動作が確認できました。

次回からは、より実践的な内容です。
OpenAMとOpenIGとの連携方法について学びます。


(参考サイト)

ForgeRock社のドキュメントを参考にさせていただきました。