目的
GlassFish/Payaraでユーザーの認証を行う場合、DBにユーザー名とパスワードを保存し、JDBCRealmに認証プロセスを任せるケースが多い。しかし、JDBCRealmはハッシュ化には対応しているものの、ソルト処理やストレッチング等はしてくれない。
glassfish-jdbc-realm-saltedを導入することで、これらの課題を解決し、より堅牢な認証プロセスを実現できる。
使い方
ほとんど公式サイトに書いてあるとおり。基本的にはJDBCRealm+αなので、JDBCRealmについては一通り理解しているものとする。
注意点
Payaraで検証したのでドメイン名がpayaradomain
になっている。GlassFishの場合はdomain1
等に適宜読み替えること。
ドメインにjarを配置する
maven centralから取ってくる。
cd /path/to/glassfish
wget http://central.maven.org/maven2/com/java-adventures/glassfish/realm/salted/glassfish-jdbc-realm-salted/0.2.0/glassfish-jdbc-realm-salted-0.2.0.jar
mv glassfish-jdbc-realm-salted-0.2.0.jar ./domains/payaradomain/lib/
ログインモジュールを登録する
echo "jdbcSaltRealm {com.ja.glassfish.auth.realm.jdbc.JDBCLoginModule required;};" >> ./domains/payaradomain/config/login.conf
Realmを作成する
asadminで作成したが、admin consoleから作成しても同じ。基本的にはJDBCRealmと同じプロパティが設定できる。追加のプロパティは公式ページ参照。
デフォルトのアルゴリズムはPBKDF2WithHmacSHA1
だが、ここではPBKDF2WithHmacSHA512
を設定している(※JavaSE8以上が必要)。
jaas-context=jdbcSaltRealm
で設定しているのが上記のログインモジュール。末尾のsaltedRealm
がRealmの名前で、これをweb.xmlに書く。
cd ./bin
./asadmin create-auth-realm --classname com.ja.glassfish.auth.realm.jdbc.JDBCRealm
--property jaas-context=jdbcSaltRealm:datasource-jndi=jdbc/Auth:user-table=t_user:group-table=t_group:user-name-column=user_name:password-column=password:group-name-column=groupname:group-table-user-name-column=user_name:pbkdf2-algorithm=PBKDF2WithHmacSHA512 saltedRealm
ウェブアプリケーションの設定
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>saltedRealm</realm-name>
</login-config>
</web-app>
パスワードのハッシュ化
Realmが担うのは認証プロセスのみなので、DBに保存するときのパスワードのハッシュ化は自前で行う必要がある。この際、Realmと同じ方法でパスワードをハッシュ化する必要がある。同じ作者がsecure-password-hashというのを公開しており、glassfish-jdbc-realm-saltedもこれを使っているので、これを使えばいいだけ。mavenならpom.xmlに以下を追加。
<dependency>
<groupId>com.java-adventures.security</groupId>
<artifactId>secure-password-hash</artifactId>
<version>1.0.1</version>
</dependency>
以下のようなコードでパスワードのハッシュ化を行う。RealmのアルゴリズムをPBKDF2WithHmacSHA512
に設定したので、ここでもそれに合わせる。他のプロパティも変更しているなら、同様にRealmに合わせる。全てのプロパティについてsetterが用意されている。
import com.ja.security.PasswordHash;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
public class PasswordHashUtil {
final PasswordHash passwordHash = new PasswordHash();
public String createHash(String password) throws InvalidKeySpecException, NoSuchAlgorithmException {
passwordHash.setPbkdf2Algorithm("PBKDF2WithHmacSHA512");
return passwordHash.createHash(password);
}
}
実行環境
$ date
2015年 10月 2日 金曜日 00時43分00秒 JST
$ ./asadmin version
Version = Payara Server 4.1.153 #badassfish (build 225)
Command version executed successfully.
$ java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.10.5
BuildVersion: 14F27