Transaction
ユーザオペレーション
ユーザオペレーション
予測不可能な利用者の操作
予測不可能な利用者の操作
z
z
二度押し
二度押し
決済処理の重複などの弊害
決済処理の重複などの弊害
z
z
ブックマークなどによる遷移への割り込み
ブックマークなどによる遷移への割り込み
ウィザードスタイルのページ遷移が破綻
ウィザードスタイルのページ遷移が破綻
z
z
リンク先を新しいブラウザで表示
リンク先を新しいブラウザで表示
同一処理が重複する可能性
同一処理が重複する可能性
z
z
ブラウザの戻るボタン
ブラウザの戻るボタン
キャッシュされた古い情報が表示される可能性
キャッシュされた古い情報が表示される可能性
アクションが再度実行される可能性
アクションが再度実行される可能性
トラブル原因はアクションの順序
トラブル原因はアクションの順序
全ては、ページとアクションが正し
全ては、ページとアクションが正し
い順序で実行されない事に起因
い順序で実行されない事に起因
サーバサイドでの現象
サーバサイドでの現象
本来の順序
本来の順序
クライアントサイド アクション A アクション B JSP1 サーバトサイド JSP2 アクション C http response http request アクション フォワード 想定遷移サーバサイドでの現象(二度押し)
サーバサイドでの現象(二度押し)
アクションB実行後、アクションBが
アクションB実行後、アクションBが
再実行
再実行
アクション フォワード二度押し
二度押し
アクション B アクション B クライアントサイド サーバトサイド JSP1 JSP2 アクション A JSP2 http response http request 想定遷移サーバサイドでの現象(遷移割込)
サーバサイドでの現象(遷移割込)
アクションAが
アクションAが
実行されないまま
実行されないまま
、アクションB
、アクションB
が実行
が実行
アクション フォワード http response http request 想定遷移 クライアントサイド サーバトサイド遷移割り込み
遷移割り込み
アクション B JSP1 JSP2 アクション A アクション Cサーバサイドでの現象
サーバサイドでの現象
(
(
.
.
do
do
Popup
Popup
)
)
アクションBが再実行
アクションBが
再実行
JSP1 クライアントサイド サーバトサイド JSP2 JSP2新しいブラウザ
新しいブラウザ
からのリクエスト
からのリクエスト
.doを popup アクション A アクション B アクション B http response http request アクション フォワード 想定遷移サーバサイドでの現象(戻るボタン
サーバサイドでの現象(戻るボタン
)
)
アクションAが
アクションAが
実行されないまま
実行されないまま
、アクションAを表示
、アクションAを表示
(キャッシュ
(
キャッシュ
)
)
アクションBを過去の状態から
アクションBを過去の状態から
再実行
再実行
過去の状態 アクション フォワード 想定遷移 アクション C アクション B クライアントサイド サーバトサイド JSP2 JSP1 アクション A アクション B http response http request予測不可能な操作を防止・検出
予測不可能な操作を防止・検出
する
する
全ては、ページとアクションが正しい順序で実
全ては、ページとアクションが正しい順序で実
行されない事に起因
行されない事に起因
完全な防止策は難しい
完全な防止策は難しい
順序不正のアクセスを防止・検出する!!
順序不正のアクセスを防止・検出する!!
方法は・・・
方法は・・・
z z次に実行されるべきアクションを保持する?
次に実行されるべきアクションを保持する?
z zReferer
Referer
にて、正しいページからの遷移かチェックす
にて、正しいページからの遷移かチェックす
る?
る?
z zJavaScript
JavaScript
を駆使する?
を駆使する?
zStruts Transaction Token
Struts Transaction Token
機能
機能
Struts
Struts
標準機能
標準機能
(
(
v1.0, v.1.1rc1)
v1.0, v.1.1rc1)
Transaction Token
Transaction Token
にてセッション毎に
にてセッション毎に
遷移を管理
遷移を管理
正しいページからのリクエストか?を検
正しいページからのリクエストか?を検
出可能
出可能
正しい処理順序か?の検出が可能
正しい処理順序か?の検出が可能
=
Struts Transaction Token
Struts Transaction Token
の仕組み
の仕組み
アクションの終了直前に
アクションの終了直前に
Transaction Token
Transaction Token
(ユ
(
ユ
ニークなキー)
ニークなキー)
をセッションに保存させる
をセッションに保存させる
レスポンス生成時に
レスポンス生成時に
JSP(Strutsカスタムタグ)
JSP(Struts
カスタムタグ)
が、
が、
Transaction Token
Transaction Token
をページに埋め込む
をページに埋め込む
ブラウザはリクエストと一緒に埋め込まれた
ブラウザはリクエストと一緒に埋め込まれた
Transaction Token
Transaction Token
を送信する
を送信する
アクションの入り口でセッションに保存されて
アクションの入り口でセッションに保存されて
いる
いる
Transaction Token
Transaction Token
とリクエストに付けられ
とリクエストに付けられ
ている
ている
Transaction Token
Transaction Token
を比較
を比較
z
z
同じなら正しいページからのリクエスト
同じなら正しいページからのリクエスト
z
Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
1.
1.
アクションの終了直前に
アクションの終了直前に
Transaction Token
Transaction Token
をセッションに保存
をセッションに保存
アクション B JSP1 アクション JSP2 アクション C
Token=T1
毎回ユニークな値が自Transaction Token動生成される セッションオブジェクト クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移
Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
2.
2.
レスポンス生成時に
レスポンス生成時に
JSP
JSP
が、
が、
Transaction Token
Transaction Token
をページに埋め込む
をページに埋め込む
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token T1が埋め 込まれたページ セッションオブジェクト Strutsカスタムタグが 自動的にTransaction Tokenをページに埋め込 む クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
3
3
.
.
ブラウザはリクエストと一緒に埋め込まれた
ブラウザはリクエストと一緒に埋め込まれた
Transaction Token
Transaction Token
を送信
を送信
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token T1が埋め 込まれたページ Token T1が 一緒に送信される セッションオブジェクト クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
4.
4.
アクションの入り口で
アクションの入り口で
Token
Token
を比較
を比較
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token T1が埋め 込まれたページ Token T1が 一緒に送信される セッションオブジェクトセッションのToken
とブラウザから
送られてき
たToken
が同じものか
比較
する
同じものなら、正しいページからのリクエスト
クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
5.
5.
再実行検出のために
再実行検出のために
Token
Token
を削除
を削除
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token T1が埋め 込まれたページ Token T1が 一緒に送信される T1が有効な期間 セッションオブジェクトToken比較後は、
再実行を検出するため
にTokenを削除する
クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
6.
6.
再度、
再度、
アクションの終了直前に
アクションの終了直前に
Transaction Token
Transaction Token
をセッションに保存
をセッションに保存
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token=T2
Token T1が埋め 込まれたページ Token T1が 一緒に送信される T1が有効な期間 セッションオブジェクト アクション終了直前に 再度Tokenを保存する 値は異なる クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token=T2
Token T1が埋め 込まれたページ Token T1が 一緒に送信される T1が有効な期間 セッションオブジェクト T2が有効な期間 Token T2が 埋め込まれ たページ Token T2が 送信される クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
二度押し・ポップアップリンクによる再実行検出
二度押し・ポップアップリンクによる再実行検出
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token=T2
Token T1が埋め 込まれたページ T1が有効な期間 セッションオブジェクト T2が有効な期間 Tokenが既に 無効なので 不正アクセス 二度押し クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
のしくみ
のしくみ
遷移割り込み検出
遷移割り込み検出
アクション B JSP1 アクション JSP2 アクション C
Token=T1
Token=T2
Token T1が埋め 込まれたページ T1が有効な期間 セッションオブジェクト T2が有効な期間 期待したToken がないため 不正アクセス遷移割り込み
遷移割り込み
Token の無 いページ クライアントサイド サーバトサイド アクション A 時間 http response 想定遷移Struts Transaction Token
Struts Transaction Token
記述方法
記述方法
JSP
JSP
を呼ぶ前のアクションにて、トークンを設定
を呼ぶ前のアクションにて、トークンを設定
z
z
Action::saveToken
Action::
saveToken( request )
( request )
JSP
JSP
内の
内の
Struts
Struts
カスタムタグで
カスタムタグで
transaction
transaction
を指定
を指定
z
z
リンク
リンク
<
<
html:link
html:link
…
…
transaction=
transaction=
“
“
true
true
”
”
>
>
にてリクエストパ
にてリクエストパ
ラメータが生成される
ラメータが生成される
z
z
フォーム
フォーム
<
<
html:form>
html:form>
は
は
saveToken
saveToken
が行われていれば、
が行われていれば、
hidden
hidden
タグ
タグ
を自動生成
を自動生成
アクションの最初にて、有効なリクエストか判定
アクションの最初にて、有効なリクエストか判定
z
z
Action::isTokenValid
Action::
isTokenValid(request, true)
(request, true)
False
False
なら不正アクセス
なら不正アクセス
Struts Transaction Token
Struts Transaction Token
記述方法
記述方法
z
z
アクションクラス
アクションクラス
public class
public class MyActionMyAction extends Action {extends Action { public
public ActionForwardActionForward execute (execute (…….) throws Exception {.) throws Exception { //
// 不正アクセス検出不正アクセス検出 boolean
boolean b = b = isTokenValid( request, true );isTokenValid( request, true ); if ( b == false ) { if ( b == false ) { // // 不正アクセス!!不正アクセス!! } } // // ビジネスロジック呼び出しビジネスロジック呼び出し …….. ActionForward
ActionForward ret = mapping.ret = mapping.findForwardfindForward((““successsuccess””););
//
// 次の呼び出しが次の呼び出しが JSP JSP ならならTokenTokenを設定を設定 if ( ret.
if ( ret.getPathgetPath().().endsWithendsWith( ( ““..jspjsp”” ) ) {) ) { saveToken
saveToken( request );( request ); } } } } } }