GlassFishの認証にPBKDF2WithHmacSHA512を使う

# 目的
GlassFish/Payaraでユーザーの認証を行う場合、DBにユーザー名とパスワードを保存し、JDBCRealmに認証プロセスを任せるケースが多い。しかし、JDBCRealmはハッシュ化には対応しているものの、ソルト処理やストレッチング等はしてくれない。
[glassfish-jdbc-realm-salted](http://www.java-adventures.com/glassfish-jdbc-realm-salted/)を導入することで、これらの課題を解決し、より堅牢な認証プロセスを実現できる。

# 使い方
ほとんど公式サイトに書いてあるとおり。基本的にはJDBCRealm+&alpha;なので、JDBCRealmについては一通り理解しているものとする。

## 注意点
Payaraで検証したのでドメイン名が`payaradomain`になっている。GlassFishの場合は`domain1`等に適宜読み替えること。

## ドメインにjarを配置する
maven centralから取ってくる。

```bash:
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/
```

## ログインモジュールを登録する

```bash:
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に書く。

```bash:
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
```
## ウェブアプリケーションの設定

```xml:web.xml
<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](https://github.com/scheuchzer/secure-password-hash)というのを公開しており、glassfish-jdbc-realm-saltedもこれを使っているので、これを使えばいいだけ。mavenならpom.xmlに以下を追加。

```xml:pom.xml
<dependency>
    <groupId>com.java-adventures.security</groupId>
    <artifactId>secure-password-hash</artifactId>
    <version>1.0.1</version>
</dependency>
```

以下のようなコードでパスワードのハッシュ化を行う。Realmのアルゴリズムを`PBKDF2WithHmacSHA512`に設定したので、ここでもそれに合わせる。他のプロパティも変更しているなら、同様にRealmに合わせる。全てのプロパティについてsetterが用意されている。

```java:PasswordHashUtil.java
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);
    }
    
}
```

# 実行環境

```bash:実行環境
$ 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

```