例えばカード決済処理の決済ボタンがあるとします。
ブラウザには「戻る」機能があるため、決済後に「戻る」をし、再度決済ボタンを押す事が可能です。
もし不適切な内部実装であれば、2重に決済してしまう可能性があります。
今回は、ログイン後の Hello 画面から「戻る」を行ってログインしようとした場合に限り、403 Forbidden を返してみます。
Gate クラスには次のメソッドが準備されています。
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
/** * 不正呼び出しの検出通知。 * @param ir 検出内容。 * @param req リクエスト。 * @param from 遷移元ページ。 * @param to 遷移先ページ。 * @return 処理の変更指示。nullなら、通常通りに動作します。 */ public Forward onIllegalRequest( IllegalRequest ir, RequestParameter req, Page from, Page to ){ // nullを返せば、通常と同じ処理がなされます。 // fromやtoの内容により、処理の中断が必要であれば、null以外の // 遷移先を返して下さい。 // 遷移先ページを指定すると、input()は呼ばれず、output()を // コールします。 return null; }
irには何が発生したかが設定されています。
| 1 | REPEAT_SAME_REQUEST | 今回の「戻る」の後の再押下のようなケースです。 ただし検出には、Page#isCheckRepeatSameRequest()でtrueを返す必要があります。 |
| 処理済みリクエストの再呼び出し。 | ||
| 2 | NOT_FOUND_HISTORY | ブラウザにURLを入力して http://localhost:8080/tutorial1/lu.tmzfgi.mo.i8qot9.on.ex257q.na を直接開いたとします(ログイン画面→Hello画面 を表すURL)。 この時、ログイン画面は履歴に存在しません。 不正アクセスが想定されます。 |
| 呼び出し元ページが履歴に存在しない。 | ||
| 3 | SESSION_ERROR | セッション自体が存在しない場合です。 しばらく操作しないでタイムアウトとなってしまったか、不正アクセスが想定されます。 |
| セッションが存在しないかタイムアウト。 |
次のような実装になります。
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
public Forward onIllegalRequest( IllegalRequest ir, RequestParameter req, Page from, Page to ){ // nullを返せば、通常と同じ処理がなされます。 // fromやtoの内容により、処理の中断が必要であれば、null以外の // 遷移先を返して下さい。 // 遷移先ページを指定すると、input()は呼ばれず、output()を // コールします。 switch( ir ) { case REPEAT_SAME_REQUEST: if ( from.getID() == PageType.LOGIN_HTML ) { return new Forward( 403 ); } break; } return null; }
今回はこのようにしましたが、通常では ir が REPEAT_SAME_REQUEST かどうかはクリティカルな画面のみで確認するようにし、あらゆる不正アクセスに対してはエラーページ(「時間が過ぎたためログアウトしました」等)へ Forward させる実装が自然でしょう。
特にそこまでのセキュリティを要求しなければ無視して常に null を返しても良いでしょう。
ただしその場合(NOT_FOUND_HISTORY や SESSION_ERROR)は履歴に過去のページが存在しないため、新規インスタンスを使って処理されます。