画面遷移の順序性の確認や サブミットボタンの二度押し(重複サブミット)の防止チェックの為に、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)とするか、トークンのオブジェクトで排他する必要がある。 |