这种使用单选按钮的表单可以安全地避免 SQL 注入吗?

Is this form using radio buttons safe from SQL Injection?

我正在尝试在我的网站上创建一个动态搜索功能,用户可以选择根据 ID、制造商、型号或日期来查找索赔信息。有一个用于输入数据的搜索栏,单选按钮提供搜索过滤器。

我想知道我的简单 if 语句方法是否存在 SQL 注入漏洞,因为我直接将变量作为列名传递(PDO 不会让您将此值传递为我理解的参数)

HTML 代码:

    <form method="POST" action="find-claims.php">
        <label for="find-claim">Find Claim:</label>
        <input type="search" id="claim-search-bar" name="claim-search-bar"><br/>
        <input type="radio" value="by-id" class="radio-param" name="search-param" checked><label for="by-id">By Claim Id</label>
        <input type="radio" value="by-make" class="radio-param" name="search-param"><label for="by-make">By Vehicle Make</label>
        <input type="radio" value="by-model" class="radio-param" name="search-param"><label for="by-model">By Vehicle Model</label>
        <input type="radio" value="by-date" class="radio-param" name="search-param"><label for="by-date">By Claim Date</label>
        <input type="submit" class="radio-param" value="Submit">
    </form>

PHP 代码:

// Get search data
$searchVal = $_POST["claim-search-bar"];

// Get radio value
$searchType = $_POST["search-param"];

// Store search type into db-naming scheme
$radioVal = "";
if($searchType == "by-id"){
    $radioVal = "claim_id";
}
else if($searchType == "by-make"){
    $radioVal = "make";
}
else if($searchType == "by-model"){
    $radioVal = "model";
}
else if($searchType == "by-date"){
    $radioVal = "date_received";
}

// DB Interaction
try{
    // Connection to DB
    require "../db-info.php";
    $dbh = new PDO("mysql:host=$serverName; dbname=$dbName", $userName, $password);
    $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

    // Get Claim based off dynamic input
    $getClaim = $dbh->prepare("SELECT * FROM claims WHERE $radioVal = ?");
    $getClaim->bindParam(1, $searchVal);
    $getClaim->execute();
    $claimInfo = $getClaim->fetchAll();

    // Checks if DB returned any data
    if($claimInfo){
        // Display corresponding info
    }
    else{
        echo "sorry no claim found";
    }

    $dbh = null;
    $stmt = null;

} catch(PDOException $e){
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

因为 $radioVal 仅分配了您在代码中编写的文字值,并且永远不会分配任何不受信任的内容,因此相对于 SQL 注入是安全的。

但是,我建议您给它一个比 "" 更好的默认值。因为如果 $searchType 的已知值中的 none 匹配,那么 $radioVal 将保持 "" 并且您将得到一个 SQL 语句:

SELECT * FROM claims WHERE  = ?

那将是一个语法错误。不会是因为SQL注入,但是不行

顺便说一句,您不需要消毒 $searchVal。这就是使用绑定参数的要点,它在 查询准备好后绑定 ,因此它不能引入 SQL 注入。消毒没消毒没关系

您可以将搜索值存储在数组中。除了删除无用的 try-catch 外,它还可以使代码的臃肿程度降低两倍。

// Get search data
$searchVal = $_POST["claim-search-bar"];

// Get radio value
$searchType = $_POST["search-param"];

// Store search type into db-naming scheme
$searchValues = [
    "by-id" => "claim_id",
    "by-make" => "make",
    "by-model" => "model",
    "by-date") => "date_received",
];
$radioVal = $searchValues[$searchType] ?? "claim_id";
// Connection to DB
require "../db-info.php";
// the connection code should really go into include

// Get Claim based off dynamic input
$getClaim = $dbh->prepare("SELECT * FROM claims WHERE $radioVal = ?");
$getClaim->execute([$searchVal]);
$claimInfo = $getClaim->fetchAll();

// Checks if DB returned any data
if($claimInfo){
    // Display corresponding info
}
else{
    echo "sorry no claim found";
}