画面遷移の順序性の確認や サブミットボタンの二度押し(重複サブミット)の防止チェックの為に、Strutsではトランザクショントークン(同期トークン)を使用する仕組みが用意されている。
トランザクショントークンは、以下のように実現される。
表示する画面の中にhiddenでランダムなID(トークン)を埋め込んでおき、そのトークンをサーバー側でもセッション内に保持しておく。
その画面でサブミットされると、hiddenに埋められていたトークンがリクエストに入れられてサーバーに届く。
サーバーでは、届いたhiddenのトークンとセッション内に保持していたトークンを比較する。一致していれば正しい遷移と判断する。
別の画面のhiddenには別のトークンが埋められている為、意図しない画面から来た場合はセッション内のトークンとは一致しないので 誤った遷移であると判断できる。
比較直後にセッション内からトークンを削除しておけば、重複サブミットの二度目の処理を防止できる。
つまり、連続してサブミットボタンが押されたような場合には同一のトークンが再び届くが、セッションのトークンは既に存在しないので一致しない。すなわち不正なサブミットだと判断できる。
トランザクショントークンは、Actionクラスのメソッドで扱う。
jspファイルで<html:form>タグを使っていれば、自動的にHTMLにトークンを埋め込んでくれる。
(<html:link>タグにtransactionという属性があるが、transaction="false"にしたらトークンが返って来ないのだろうか)
| メソッド名 | 概要 |
|---|---|
| saveToken() | 新しいトークンを生成してセッションの中に保存する。 |
| isTokenValid() | リクエストに入っているトークンがセッションで保持しているトークンと等しいかどうかチェックする。 第2引数がtrueだと、判定時にトークンを削除する。 |
| resetToken() | セッションに保持されているトークンを削除する。 ただし、以下のような使い方をすべきではない。 if (isTokenValid(req)) {
resetToken(req);
}
なぜなら、サブミットボタンを連続押しされた場合は、isTokenValid()とresetToken()の間に別スレッドが該当トークンオブジェクトを使って判定するかもしれないから。素直にisTokenValid(req, true)とするか、トークンのオブジェクトで排他する必要がある。 |