kazpgmの日記

『プログラム自動作成@自動生成』作成の日記

TOOL更新_63.クロスサイトリクエストフォージェリ対策として、DB追加、更新、削除の画面でトークンチェックを行う。作成完了。

TOOL更新_63.クロスサイトリクエストフォージェリ対策http://d.hatena.ne.jp/kazpgm/20090403/1238773943として、DB追加、更新、削除の画面でトークンチェックを行う。作成完了。 (ダブルクリック防止も同時に行っている。)
http://d.hatena.ne.jp/kazpgm/20090524/1243113458 、http://d.hatena.ne.jp/kazpgm/20090525/1243262315(5月24、25に一度作ったが、いろいろな理由でボツにした。)本日このロジックで自動作成することにした。


■TokenHandle.php (トークンチェッククラス)

<?php
//トークンチェッククラス
class TokenHandle {

    // トークンHidden取得
    function getTokenHtml($base = "") {
        // トークン作成
        $latest_token =  md5(uniqid(rand(),TRUE));
        if (!is_array($_SESSION['KAZ_TOOL_token'])) { // トークンは配列で保存する
            $_SESSION['KAZ_TOOL_token'] = array();
        } else {
            if (count($_SESSION['KAZ_TOOL_token']) > 9) { // トークンは直近10個保存
                array_shift($_SESSION['KAZ_TOOL_token']);
            }
        }
        if (!is_array($_SESSION['KAZ_TOOL_token_time'])) { // トークン時間は配列で保存する
            $_SESSION['KAZ_TOOL_token_time'] = array();
        } else {
            if (count($_SESSION['KAZ_TOOL_token_time']) > 9) { // トークン時間は直近10個保存
                array_shift($_SESSION['KAZ_TOOL_token_time']);
            }
        }
        $_SESSION['KAZ_TOOL_token'][$latest_token] = $latest_token; // トークン保存
        $_SESSION['KAZ_TOOL_token_time'][$latest_token] = time();   // トークン時間保存

        if ($base == "") {
            return '<input type="hidden" name="KAZ_TOOL_token" value="'. $latest_token .'" />' ;
        } else {
            return 'KAZ_TOOL_token='. $latest_token;
        }
    }


    // トークンチェック
    function isTokenValid($mode, $userFlg = true) {
        $modeMach = false; // トークンチェックフラグ初期化
        $mode_ary = explode(',', 'ins_do,upd_do,del_do' ); // トークンチェック対象モード配列
        for($i = 0; $i < count($mode_ary); $i++) {
            if (trim($mode_ary[$i]) == $mode) { // 'ins_do,upd_do,del_do'の中にあれば
                $modeMach = true;  // トークンチェックする
                break;
            }
        }

        if ($modeMach == true) { // トークンチェックする場合
            if (!empty($_SESSION['KAZ_TOOL_token']) && is_array($_SESSION['KAZ_TOOL_token']) &&
                $_REQUEST['KAZ_TOOL_token'] == $_SESSION['KAZ_TOOL_token'][$_REQUEST['KAZ_TOOL_token'] ]) {
                $token_age = time() - $_SESSION['KAZ_TOOL_token_time'][$_REQUEST['KAZ_TOOL_token'] ];
                if (($userFlg == false && 
                     $token_age > (180 * 60)) || // 管理者は3時間OK
                    ($userFlg == true && 
                     $token_age > (60 * 60))) { // ユーザは1時間OK(深い理由はない)
                    // OK:トークン削除
                    unset($_SESSION['KAZ_TOOL_token'][$_REQUEST['KAZ_TOOL_token'] ]);
                    unset($_SESSION['KAZ_TOOL_token_time'][$_REQUEST['KAZ_TOOL_token'] ]);
                }
            } else {
                return false;
            }
            return true;
        }
        // OK
        return true;
    }
}
?>

■プログラムに追加

・管理者側:
require_once('TokenHandle.php');

if (TokenHandle::isTokenValid($mode, false) == false) { // 管理者側
    // トークンチェックエラー場合
    echo 'Message: ' . 'The token error occurred. ' . "<br />\n";
    exit;
}
unset($_REQUEST['KAZ_TOOL_token']);

・ユーザ側:
require_once('TokenHandle.php');

if (TokenHandle::isTokenValid($mode, true) == false) { // ユーザ側
    // トークンチェックエラー場合
    echo 'Message: ' . 'The token error occurred. ' . "<br />\n";
    exit;
}
unset($_REQUEST['KAZ_TOOL_token']);

■htmlプログラムに追加

require_once('TokenHandle.php');
<?= TokenHandle::getTokenHtml(); ?>

■2度押しした場合トークンチェックエラーになってしまうので、このJavaScriptで2度押しできないようにしておく。
<=7/23 トークンは直近10個残すようにしたので、2度押しでのトークンチェックエラーは起きないということに気づいた。

・htmlに追加、修正  例):itemUaddConfirmView.htm_
<script type="text/javascript" src="/kaz01u/admin/js/kaz.js"></script>

<a href="javascript:do_Submit_CLK2('ins_do');"><img src="/kaz01u/img/btn/btn_entry.gif" alt="登録" width="61" height="22" border="0" class="right5" /></a>

kaz.js を新規で作成する。

    var doubleClick_flg = true;
    //Submit制御(DoubleClick制御あり)
    function do_Submit_Clk1() {
        if (doubleClick_flg == true) {
            window.setTimeout(function() { doubleClick_flg = false; }, 1);
            window.setTimeout(function() { doubleClick_flg = true; }, 1000);
            document.frm.submit();
        } else {
            return; false;
        }
    }

    //Submit制御(DoubleClick制御あり)
    function do_Submit_Clk2(mode) {
        if (doubleClick_flg == true) {
            window.setTimeout(function() { doubleClick_flg = false; }, 1);
            window.setTimeout(function() { doubleClick_flg = true; }, 1000);
            document.frm.mode.value = mode;
            document.frm.submit();
        } else {
            return; false;
        }
    }

■サイト:http://kazpgm.ddo.jp/

7/22 21:00-06:00