PHP/MySQL-验证用户名,但附加字符除外

PHP/MySQL-验证用户名,但附加字符除外,php,mysql,validation,Php,Mysql,Validation,我已经使用PHP和MySQL创建了一个体育联赛网站,其中包含动态时间表和排名。该网站的一个基本功能是让学校根据时间表选择一个已经玩过的游戏,并登录报告分数。您可以在下面看到分数报告页面的示例: 经过几个月的工作,一切似乎都很正常。然而,今天早上,就在新赛季的日程即将开始之前,我意识到了一个重要的疏忽: 我们的一些学校在每个部门都有多个团队,因为他们有额外的学生。例如,可能有一个圣芭芭拉和一个圣芭芭拉2参加同一个联赛和/或分区。有时,四支球队中有三支来自较大的学校 这是一个问题,因为我编写的验证代

我已经使用PHP和MySQL创建了一个体育联赛网站,其中包含动态时间表和排名。该网站的一个基本功能是让学校根据时间表选择一个已经玩过的游戏,并登录报告分数。您可以在下面看到分数报告页面的示例:

经过几个月的工作,一切似乎都很正常。然而,今天早上,就在新赛季的日程即将开始之前,我意识到了一个重要的疏忽:

我们的一些学校在每个部门都有多个团队,因为他们有额外的学生。例如,可能有一个圣芭芭拉和一个圣芭芭拉2参加同一个联赛和/或分区。有时,四支球队中有三支来自较大的学校

这是一个问题,因为我编写的验证代码检查学校用户名,确保它们与MySQL数据库中的master school用户帐户匹配,然后才允许报告分数。因此,圣巴巴拉不会被授权报告他们的圣巴巴拉2队的得分,即使他们属于同一所学校!我不想为属于那个学校的每个团队创建单独的用户帐户,所以我需要以某种方式修改代码。我希望St.Barbara能够使用相同的用户名登录他们所有的不同团队,不管最后是否有其他字符(如果有意义的话)

下面是我的脚本中的函数,它验证用户名school,以确保他们是参与讨论中游戏的两个团队之一:

// 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';
}
可以这么说,是否有必要在守则中增加一个附录,作为拥有多个团队的学校的例外?有点像:

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);

?>

目前,我假设您正在验证$\u POST['away\u team']和$\u POST['home\u team']是否有效和正确

如果您只想检查$\u POST['away\u team']是否以字符串$\u POST['school']开头,可以使用以下函数:

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';
}

使用mysqli的占位符特性和添加数据的方法比使用字符串插值要好得多。您还差一个巨大的SQL注入错误,它可能会在没有隔离的情况下破坏您的应用程序。谢谢您的反馈。我一定会调查的。不管它值多少钱,我都会在脚本中对这两个分数进行验证,使用isnumeric尝试阻止SQL注入。无论您认为自己做了多少清理或清理,都需要对所有内容进行转义。这是你的最后一道防线,最好是一道好防线。占位符通常使您的SQL代码更易于阅读,这是一个额外的好处。我刚刚意识到,事实上,我正在使用mysqli\u real\u escape\u字符串并在将值提交到数据库之前修剪脚本中的其他位置。我已经发布了上面的全部代码。这与您所指的内容一致吗?您的查询应该类似于WHERE school_name=?然后在事实发生后将$loser的值绑定在那里。这使得查询代码更具弹性,如果查询字符串中没有插入任何内容,就更难出错。您使用mysqli就像使用mysql\u查询一样,这是一个错误。这个方法比程序性方法好得多,所以我建议用它来代替。它使您的代码更加清晰。谢谢!粘贴时,我在代码的回显部分出错。我确实想确认它们是正确的,而不是错误的。这似乎正是我要找的。我会测试它的!sprintf是bind_param的一个差劲的替代品。没错,但它立即比他正在做的要好。要使用bind_param,您需要使用预先准备好的语句,每个人都应该这样做,但这是一个更困难的更改。如果体系结构假设所有查询都由字符串充分表示,那么如果不进行更彻底的重新设计,则可能无法进行更改。@meustrus如果有帮助,我只是发布了整个脚本,以便您可以看到我实施的流程和安全措施。如果您愿意,欢迎您提出任何建议。再次谢谢你。@meustrus这真的不是一个困难的改变。这只是一个额外的一两行取决于你怎么做。
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';
}
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
    }
}