0

PHP と MySQL を使用して、動的なスケジュールと順位を表示するスポーツ リーグの Web サイトを作成しました。ウェブサイトの基本的な機能の 1 つは、学校が既にプレイされたスケジュールでゲームを選択し、ログインしてスコアを報告することです。スコア レポート ページの例を以下に示します。

http://www.parochialathleticleague.org/report_score.html?league=test_league&game_id=5&away_team=St.%20Polycarp&home_team=St.%20Columban

数か月の作業の後、すべてがうまく機能しているようです。しかし、今朝、新しいシーズンのスケジュールが開始される直前に、1 つの重要な見落としに気付きました。

私たちの学校の中には、余分な生徒がいるため、各部門に複数のチームがある学校もあります。したがって、たとえば、同じリーグや部門に参加しているセント バーバラとセント バーバラ #2 が存在する場合があります。場合によっては、大規模な学校から 4 チームのうち 3 チームが参加することもあります。

私が書いた検証コードは、学校のユーザー名をチェックして、スコアの報告を許可する前に、MySQL データベース内のマスター学校のユーザー アカウントと一致することを確認するため、これは問題です。したがって、St. Barbara は、同じ学校に所属していても、St. Barbara #2 チームのスコアを報告する権限がありません! その学校に所属するチームごとに個別のユーザー アカウントを作成したくないので、何らかの方法でコードを変更する必要があります。最後に追加の文字があるかどうかに関係なく、St. Barbara がすべての異なるチームで同じユーザー名でログインできるようにしたいと思います (それが理にかなっている場合)。

ユーザー名 (学校) を検証して、問題のゲームに参加している 2 つのチームのいずれかであることを確認するスクリプトの関数を次に示します。

// Validate the school:
if (empty($_POST['school'])) {
    echo "You forgot to enter your school.<br>";
    $validate = 'false';
} elseif ($_POST['school'] != $_POST['away_team'] && $_POST['school'] != $_POST['home_team']) {
    echo "Your school does not match one of the two on file for this game.<br>";
    $validate = 'false';
} else {
    $school = mysqli_real_escape_string($db, trim($_POST['school']));
    $validate = 'true';
}

次に、ユーザー名とパスワードがデータベース内のレコードの 1 つと一致することを後で検証する関数を次に示します。

// If all conditions are met, process the form:
if ($validate != 'false') {
    $q1 = "SELECT school_id FROM user_schools WHERE (school_name='$school' AND pass='$pass')";
    $r1 = mysqli_query($db, $q1);
    $num = mysqli_num_rows($r1);
    if ($num == 1) { 
// ***a whole bunch of other stuff that I'm omitting because it's not relevant
    }
}

複数のチームを持つ学校を例外とするコードに、いわば「補遺」を追加する方法はありますか? のような並べ替え:

elseif ($_POST['school'] == $_POST['away_team'] **MINUS ADDITIONAL INTEGERS AT THE END** || $_POST['school'] == $_POST['home_team'] **MINUS ADDITIONAL INTEGERS AT THE END**) {
        $validate = 'true';
    }

全体的に長文ですみません。きちんと説明したかっただけです!何かご意見は?フィードバックをお待ちしております。

編集 - 興味のある人のためのスクリプト全体は次のとおりです。

<?php

// Connect to the database:
require ('../mysqli_connect.php');

// Validate the school:
if (empty($_POST['school'])) {
    echo "You forgot to enter your school.<br>";
    $validate = 'false';
} elseif ($_POST['school'] != $_POST['away_team'] && $_POST['school'] != $_POST['home_team']) {
    echo "Your school does not match one of the two on file for this game.<br>";
    $validate = 'false';
} else {
    $school = mysqli_real_escape_string($db, trim($_POST['school']));
    $validate = 'true';
}

// Validate the password:
if (empty($_POST['pass'])) {
    echo "You forgot to enter your password.<br>";
    $validate = 'false';
} else {
    $pass = mysqli_real_escape_string($db, trim($_POST['pass']));
    $validate = 'true';
}

// Validate the away score:
if (!isset($_POST['away_score'])) {
    echo "You forgot to enter the away score.<br>";
    $validate = 'false';
} elseif (!is_numeric($_POST['away_score'])) {
    echo "You entered an invalid score for the away team.<br>";
    $validate = 'false';
} else {
    $away_score_confirm = mysqli_real_escape_string($db, trim($_POST['away_score']));
    $validate = 'true';
}

// Validate the home score:
if (!isset($_POST['away_score'])) {
    echo "You forgot to enter the home score.<br>";
    $validate = 'false';
} elseif (!is_numeric($_POST['$home_score']) && $_POST['$home_score'] < 0 ) {
    echo "You entered an invalid score for the home team.<br>";
    $validate = 'false';
} else {
    $home_score_confirm = mysqli_real_escape_string($db, trim($_POST['home_score']));
    $validate = 'true';
}

// Determine the winner and loser, and set variables:
if ($_POST['away_score'] > $_POST['home_score']) {
    $winner = mysqli_real_escape_string($db, trim($_POST['away_team']));
    $winner_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
    $loser = mysqli_real_escape_string($db, trim($_POST['home_team']));
    $loser_score = mysqli_real_escape_string($db, trim($_POST['home_score']));
    $tie = 'no';
} else if ($_POST['away_score'] < $_POST['home_score']) {
    $winner = mysqli_real_escape_string($db, trim($_POST['home_team']));
    $winner_score = mysqli_real_escape_string($db, trim($_POST['home_score']));
    $loser = mysqli_real_escape_string($db, trim($_POST['away_team']));
    $loser_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
    $tie = 'no';
} else if ($_POST['away_score'] == $_POST['home_score']) {
    $tie = 'yes';
    $tie1 = mysqli_real_escape_string($db, trim($_POST['away_team']));
    $tie2 = mysqli_real_escape_string($db, trim($_POST['home_team']));
    $tie_score = mysqli_real_escape_string($db, trim($_POST['away_score']));
}

// Declare remaining hidden inputs as variables:
$league = mysqli_real_escape_string($db, $_POST['league']);
$game_id = mysqli_real_escape_string($db, $_POST['game_id']);

// If all conditions are met, process the form:
if ($validate != 'false') {
    $q1 = "SELECT school_id FROM user_schools WHERE (school_name='$school' AND pass='$pass')";
    $r1 = mysqli_query($db, $q1);
    $num = mysqli_num_rows($r1);
    if ($num == 1) {
        // Get the game ID:
        $q2 = "SELECT $game_id FROM $league";
        $r2 = mysqli_query($db, $q2);
        // Get the row for the game ID:
        $row = mysqli_fetch_array($r2, MYSQLI_NUM);
        // Perform an UPDATE query to modify the game scores:
        $q3 = "UPDATE $league SET home_score='$home_score_confirm', away_score='$away_score_confirm' WHERE game_id=$row[0]";        
        $r3 = mysqli_query($db, $q3);
        if (mysqli_affected_rows($db) == 1) {
            $confirm = 'true';
        } else {
            $confirm = 'false';
        }

        // Update the winning team in the standings:
        $q4 = "SELECT school_id FROM test_league_standings WHERE school_name='$winner'";
        $r4 = mysqli_query($db, $q4);
        // Get the row for the school:
        $row2 = mysqli_fetch_array($r4, MYSQLI_NUM);
        $q5 = "UPDATE test_league_standings SET games=games + 1, win=win + 1, pts_for=pts_for + '$winner_score', pts_against=pts_against + '$loser_score' WHERE school_id=$row2[0]";
        $r5 = mysqli_query($db, $q5);
        $q6 = "UPDATE test_league_standings SET pct=(win / games), avg_for=(pts_for / games), avg_against=(pts_against / games) WHERE school_id=$row2[0]";
        $r6 = mysqli_query($db, $q6);
        if (mysqli_affected_rows($db) == 1) {
            $confirm = 'true';
        } else {
            $confirm = 'false';
        }

        // Update the losing team in the standings:
        $q7 = "SELECT school_id FROM test_league_standings WHERE school_name='$loser'";
        $r7 = mysqli_query($db, $q7);
        // Get the row for the school:
        $row3 = mysqli_fetch_array($r7, MYSQLI_NUM);
        $q8 = "UPDATE test_league_standings SET games=games + 1, loss=loss+1, pts_for=pts_for + '$loser_score', pts_against=pts_against + '$winner_score' WHERE school_id=$row3[0]";
        $r8 = mysqli_query($db, $q8);
        $q9 = "UPDATE test_league_standings SET pct=(win / games), avg_for=(pts_for / games), avg_against=(pts_against / games) WHERE school_id=$row3[0]";
        $r9 = mysqli_query($db, $q9);
        if (mysqli_affected_rows($db) == 1) {
            $confirm = 'true';
        } else {
            $confirm = 'false';
        }

        if ($confirm != 'false') {
            header("Location: schedules_test.html?league=" . $league);
        } else {
            echo "The scores could not be reported due to a system error. Apologies for the inconvenience. If this problem continues, please contact us directly.";
        }

    } else {
        echo "Your school and password combination do not match those on file for this game.";
    }       
}

mysqli_close($db);

?>
4

1 に答える 1

1

今のところ、あなたがそれを検証しており、有効で正しいと仮定し$_POST['away_team']ます$_POST['home_team']

stringで$_POST['away_team'] 始まることを確認したいだけの場合は、次の関数$_POST['school']を使用できます。strpos

elseif (strpos($_POST['away_team'], $_POST['school']) === 0 || strpos($_POST['home_team'], $_POST['school'])) {
    echo "Your school does not match one of the two on file for this game.<br>";
    $validate = 'false';
}

SQL インジェクションに関する tadman のコメントに同意したいと思います。クエリにデータを挿入する優れた方法を利用するためにアプリケーションを書き直す気がない場合でも、クエリを実行するときは絶対にデータをエスケープする必要があります。他の場所でエスケープしないでください。そうした場合、最終的にはそれをエスケープすることを忘れてしまい、本来あるべきほど明白ではなくなります。例えば:

if ($validate != 'false') {
    $q1 = sprintf(
        "SELECT school_id FROM user_schools WHERE (school_name='%s' AND pass='%s')",
        mysqli_real_escape_string($_POST['school']),
        mysqli_real_escape_string($_POST['pass'])
    );
    $r1 = mysqli_query($db, $q1);
    $num = mysqli_num_rows($r1);
    if ($num == 1) { 
// ***a whole bunch of other stuff that I'm omitting because it's not relevant
    }
}
于 2013-09-12T19:23:18.233 に答える