Play Frameworkのアプリ内にパスワード生成プロジェクトを追加

Webアプリケーションのユーザをテーブルで管理する場合MySQLなどのDBで、SHA2()関数などを使ってパスワードを変換しても良いのだが、プログラム側で生成するとした場合は開発中のテストユーザのパスワードを生成するのに困る。

Play Frameworkの場合はBCryptを使う例を見かけたのでこれを使うタスクをSBTで定義できたら良いのかな、と考えた。
…が、結局(知識不足なためだろうが)うまくできずサブプロジェクトとして用意して解決できたのでそのメモ。
(Play Frameowrk 2.3.8, Java 7)

build.sbt

ルートプロジェクトのbuild.sbtに以下を追加して、passgenというプロジェクトを登録する。
(名前は何でも良いが、変更する場合は以降の文字列も読み替えてください)
この書き方だとpassgenというディレクトリがプロジェクトのディレクトリになる。

lazy val passgen = project

プロジェクト追加

passgenというディレクトリを追加して、build.sbtを作成。
jbcryptというdependencyを使うので、以下のようにする。

libraryDependencies ++=  Seq(
  javaCore,
  "org.mindrot" % "jbcrypt" % "0.3m"
)

ジェネレータ作成

Javaで書いているが、ScalaでもOK(なはず)。
passgen/src/main/java/PassGen.javaを作成し、以下のようにする。

import org.mindrot.jbcrypt.BCrypt;

public class PassGen {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("Password string is required");
            System.exit(0);
        }
        String password = args[0];
        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt(8));
        System.out.println(hashedPassword);
    }
}

実行

activatorを実行し、以下のように操作する。

(passgenプロジェクトに移動)
$ project passgen

(パスワード生成)
> run password
(出力された値をパスワードとしてテスト用SQLなどに貼り付ける)

(rootに戻るときは以下を実行)
> project root

プロジェクトにした理由

当初はSBTだけで解決しようとしたのだが、dependencyを使ったところ認識してくれず断念した。
build.sbtでは式しか書けない、というのは分かっていてBuild.scalaなどに分離して記述したのだがbuild.sbtに書いているdependency (jbcrypt)が認識されない。
これができていたら、全体としてもう少しスマートに書ける気がするのだが…。
独自タスクを作成する方法はSBTのマニュアルにも書いてあるのだが、独自タスクの中でdependencyを取り扱う方法がわからなかった。
Gradleはこの点で特別なことをすることなく簡単に書けるので楽だなと感じる。(単純に自分の理解度の差かもしれないが)

その他

今回はやらなかったが、ルートプロジェクトと同じdependencyを使うので、各build.sbtでそれぞれバージョン指定するのではなく、どこかでまとめた方が良いはず。
さらに、saltのパラメータなどはプロジェクト本体と共通でなければならないので本体プロジェクトがpassgenプロジェクトを参照するような形にした方が良いはず。

© 2010 ksoichiro