我正在用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);
?>
答案 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时,将这些值添加并执行,从而使这些攻击变得不可能(如果正确完成的话)。
我发现显示一个示例有助于说明这有多糟糕。那就是说,我不打算编写有关如何正确准备查询的教程,因为网络上有很多东西。
干杯!