【问题标题】:PHP script throwing 500 internal errorPHP脚本抛出500内部错误
【发布时间】:2014-03-12 04:21:37
【问题描述】:

我有一个 Javascript 脚本,它通过 POST 将 Ajax 请求发送到以下 PHP 脚本。 $db 是从上面传递的,但我知道那部分有效。我收到了 500 内部服务器错误。我无法查看服务器日志,因此无法获得比这更详细的信息。有谁知道我可以做些什么来解决它?

function register($db) {
    $user = $_POST['username'];
    $pass = $_POST['password'];

    $query = "SELECT username FROM users WHERE username='$user'";
    $result = mysqli_query($db, $query);
    if (mysqli_fetch_array($result)[0] == $user) {
        echo "taken";
    }
    else {
        $query = "INSERT INTO users (username, password) VALUES ('$user', '$pass')";

        if (mysqli_query($db, $query)) {
            echo "success";
        }
    }
}

【问题讨论】:

  • 可爱的SQL injection attack 漏洞。您是否使用最新的 PHP 版本,例如5.4+?您的 mysqli_fetch_array()[0] 在早期 PHP 中是非法语法。
  • 还有其他 PHP 脚本可以在这个服务器上运行吗?
  • 请检查您服务器中的文件权限和.htaccess文件
  • 检查你的 PHP 版本是否支持()[] -> 从数组函数中获取元素。
  • @NinjaDevelopers:呃,我不是这么说的。您现在正在混合使用 mysql 和 mysqli 库。如果可以的话,我会 -1 你...

标签: php ajax


【解决方案1】:

这更像是一个推论,而不是一个实际的答案,但对于评论的格式来说它太长了。

为了跟进@MarcB 的评论,您应该将代码更改为不受 SQL 注入攻击:

$user = $_POST['username'];
$pass = $_POST['password'];

$link = new mysqli($host, $username, $password, $database);
if(!$link)
{
    die("Unable to connect to MySQL");
}

$stmt = $link->prepare("SELECT username FROM users WHERE username=?");
$stmt->bind_param("s", $user);
$stmt->bind_result($testUsername);
$stmt->execute();
$stmt->store_result();
$stmt->fetch();

if($stmt->num_rows > 0)
{
    echo "taken";
}
else
{
    $stmt = $link->prepare("INSERT INTO users (username, password) VALUES(?, ?)");
    $stmt->bind_param("ss", $user, $pass);
    $stmt->execute();

    echo "success";
}

【讨论】:

    【解决方案2】:

    我相信您有一个解析错误,该错误已在更高版本的 PHP 中得到修复。以下代码行无效

    if (mysqli_fetch_array($result)[0] == $user) {
    

    为了解决这个问题,您需要将该行更改为以下内容:

    $row = mysqli_fetch_array($result);
    if ($row[0] == $user) {
    

    此外,您的代码还存在相当严重的 SQL 注入漏洞。在查询中使用它们之前,您需要清理变量。对于整数和浮点数,我建议您执行以下操作:

    $myInt   = (isset($_POST['myInt'])   ?   (int)$_POST['myInt']   : null);
    $myFloat = (isset($_POST['myFloat']) ? (float)$_POST['myFloat'] : null);
    

    对于字符串,您应该使用mysqli_real_escape_string(),如下所示:

    $myStr = (isset($_POST['myStr']) ? mysqli_real_escape_string($_POST['myStr']) : null);
    

    在您的情况下,您的 $user$pass 变量需要像上面的字符串一样进行清理。强制您通过$_POST 接收的数字类型的原因是它完全否定了某人通过无效值的任何可能性。任何不是 0、1、2、3、4 等的被转换为 (int) 的东西都会变成 0。

    【讨论】:

    • 太棒了,谢谢!我一直在为这个愚蠢的问题挠头好几个小时。虽然这个脚本不需要以任何方式保证安全,但我确实需要学习准备好的语句和诸如此类的东西。我会落实你的建议。谢谢!
    • @David 上面的回答是你应该如何正确使用 mysqli() 类以及准备好的语句和绑定参数来做到这一点,但是在项目中混合样式可能会导致痛苦。如果您的代码已经使用了函数别名(例如,mysqli_query()mysqli_fetch_assoc() 等),那么您最好坚持使用该样式,直到您可以用新样式替换所有数据库代码。跨度>
    • 另外,您可能希望使用mysqli_fetch_assoc() 而不是_array,因为它允许您使用$row['user'] 而不是$row[0] 来获取值,这更具可读性。
    • 太棒了,我会尽快调查的。到目前为止,我在各种语言之间有大约 1000 行代码,但这不会太痛苦。无论如何,我需要学习准备好的语句并清理我的输入。
    猜你喜欢
    • 2017-11-06
    • 2016-03-23
    • 2011-07-04
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    相关资源
    最近更新 更多