PHP检查一个ID是否与活动ID相关联

时间:2019-02-07 18:43:06

标签: php mysql

我正在用PHP做一个项目,就像一个帮助台(对编程世界来说是新的)。 每个员工($ zaposlenik)可以回答每个问题一次。如果他已经回答了选定的问题,则应将其重定向到mojaTvrtka.php(他工作场所的主页),并且应该出现回声,表明“您已经准备好回答该问题”。我不确定为什么它行不通。 IF的else部分工作正常。

<?php 
include("baza.php");
include("header.php");

$pid=$_POST['id'];
$zaposlenik=$_SESSION['activeUserId'];
$tekst=$_POST["tekstOdgovora"];
$datum=date('Y-m-d H:i:s');

$connect=connectDB();
$query1="SELECT pitanje_id,odgovor.zaposlenik_id AS odgZap
FROM odgovor
LEFT JOIN zaposlenik
ON odgovor.pitanje_id=zaposlenik.korisnik_id
WHERE odgovor.zaposlenik_id='$activeUserId'";

$result1=queryDB($connect,$query1);

if(mysqli_num_rows($result1) == $zaposlenik))
{
        header("Location:mojaTvrtka.php");
        echo "Vec ste odgovorili na ovo pitanje!";
}
else 
{
    $query="INSERT INTO odgovor
    (pitanje_id,zaposlenik_id,tekst,datum_vrijeme_odgovora) VALUES ('$pid','$zaposlenik','$tekst','$datum')";

    $result=queryDB($connect,$query);

header("Location: detaljiPitanja.php?id=$pid");
}

disconnectDB($connect);
?>

1 个答案:

答案 0 :(得分:0)

几件事,

网络是无状态的,这意味着从一个请求到另一个请求是分开完成的(稍后会详细介绍)

在您的代码中

if(mysqli_num_rows($result1) == $zaposlenik))
{
    $message = urlencode("Vec ste odgovorili na ovo pitanje!"); //make sure to url encode it, so it's safe for query args
    header("Location:mojaTvrtka.php?flash_message=$message"); //pass message via the url
    exit(); //always exit after header, ABSOLUTELY no output is allowed before header
}

现在,由于的无状态性质,我们必须使用某种持久性存储来传递消息。数据不会跨请求传递。这就是为什么您的回声不起作用的部分原因。另一个原因是,即使您确实回显了页面,页面也会重定向,因此没有人可以看到它。最简单(也是最丑陋)的方法是将该消息作为url的一部分传递。

在标头重定向之后使用exit非常重要。在此之后做事会导致“奇怪”的事情发生。

然后在指向您的页面上

 $flash_message = isset($_GET['flash_message']) ? "<div class=\"flash_message\" >{$_GET['flash_message']}</div>" : '';

 echo $flash_message;

未经测试,但很简单。

另一部分

你有这个:

  if(mysqli_num_rows($result1) == $zaposlenik))

基本上,您在这里所说的是activeUserId的值应与结果数匹配。因此,如果我的ID为120292,那么我必须确切地知道此条件返回的数字或行为false。然后会触发else,当然会触发$query="INSERT INTO odgovor

实际上,您只想知道它们是否有1行。所以

 if(mysqli_num_rows($result1) == 1)//returns exactly 1 rows

或者您可以通过这种方式简单地检验其真实性

if(mysqli_num_rows($result1)) //returns some number of rows

最后一件事

即使我看不懂此内容:

$query1="SELECT pitanje_id,odgovor.zaposlenik_id AS odgZap
     FROM odgovor
     LEFT JOIN zaposlenik
     ON odgovor.pitanje_id=zaposlenik.korisnik_id
     WHERE odgovor.zaposlenik_id='$activeUserId'";

我可以告诉您是否需要匹配用户ID和问题ID,您只有一个WHERE条件。因此,您可能需要在此处为​​问题ID添加一些内容。我假设存在某种形式的关系(我认为是答案表),它与问题表相关。例如外键(问题ID)。因此,您只需要添加它,然后获取有问题的问题的ID(请参阅我在那做的事情)。

//Obviously this is just PSUDO code, so replace this with your actual field and value...
WHERE odgovor.zaposlenik_id='$activeUserId' AND question_id='$questionId'";

SQL注入

此外,odgovor.zaposlenik_id='$activeUserId'这些东西对于SQL Injection来说是非常重要的,因此请使用准备好的语句。

注射的例子是这样:

   $activeUserId = "' OR 1 LIMIT 1 --";

这将使您的查询如下:

   SELECT pitanje_id,odgovor.zaposlenik_id AS odgZap
   FROM odgovor
   LEFT JOIN zaposlenik
   ON odgovor.pitanje_id=zaposlenik.korisnik_id
   WHERE odgovor.zaposlenik_id='' OR 1 LIMIT 1 --'

--是SQL中注释的开始,因此之后没有任何运行。这样做是选择第一行(OR 1始终为true),然后仅返回该行。

在这种情况下,这很普通,因为它们的行为就像他们回答了问题一样,但是关键是我能够对数据库执行我想要的任何SQL命令。假设用户输入找到了进入$activeUserId的方式,即使这样做也不值得冒险吗?

通过准备好的语句,您可以像这样执行SQL;

    WHERE odgovor.zaposlenik_id=? AND question_id=?

当您准备它时,DB会解析SQL,说没关系。然后,在数据库不知道使它们成为SQL时,将这些值添加并执行,从而使这些攻击变得不可能(如果正确完成的话)。

我发现显示一个示例有助于说明这有多糟糕。那就是说,我不打算编写有关如何正确准备查询的教程,因为网络上有很多东西。

干杯!