【问题标题】:Why is my database not being updated when someone visits my website?为什么有人访问我的网站时我的数据库没有更新?
【发布时间】:2011-03-23 00:41:07
【问题描述】:

由于某种原因,当用户来到我的网站玩多人游戏时,会发送对 php 文件的调用,但数据库不会添加新玩家或更新他们的信息。

使用 javascript 文件中的以下代码行调用 php 文件:

xmlhttp.open('GET',"xml_http_request.php?mod0="+truckHeading+"&mod1="+newhtr[1]+"&mod2="+absRoll+"&lla0="+lla[0]+"&lla1="+lla[1]+"&lla2="+lla[2]+"&pid="+rCC+"&rangeCheck="+rangeCheck+"&ranger="+ranger+"&namely="+namely+"&message="+message+"&unLoader=false", true);

这是 php 代码:

<?php
require("db1.php"); //for using live public database
//require("db.php"); //for using local database

$inserter=0;

//assign pid if have not already
$pid=$_GET['pid'];
if($pid=='false'){
  $inserter=1;
  $query="SELECT id FROM positioner";
  $result=mysql_query($query);
  $num_rows=mysql_num_rows($result);
  $i=1;
  while($row=@mysql_fetch_assoc($result)){
    if($i!=$row['id']){ $pid=$i;break; } //take first available id
    $i++;
  }
  if($pid=='false'){ $pid=$num_rows+1; }  //if no hole in id list, take next one higher
  mysql_free_result($result);
}

$unLoader=$_GET['unLoader'];

if($unLoader=='true'){
  $ddb=dbq("DELETE FROM positioner WHERE id = '".$pid."' LIMIT 1;");
}else{

  $dbMi=$_GET['dbMi'];

  $mod0=$_GET['mod0'];
  $mod1=$_GET['mod1'];
  $mod2=$_GET['mod2'];

  $lla0=$_GET['lla0'];
  $lla1=$_GET['lla1'];
  $lla2=$_GET['lla2'];

  $rangeCheck=$_GET['rangeCheck'];
  $namely=addslashes($_GET['namely']);
  if($namely==''){ $namely='x'; }
  $message=addslashes($_GET['message']);

  $rangeCheck='true';
  //only check range every x number of ticks (50, ~3 seconds)?
  // , $rangeCheck is true first time
  if($rangeCheck=='true'){
    $ranger=array();
    //get lat lon of all for determining who is in range
    $query="SELECT id, lla0, lla1 FROM positioner WHERE id != '".$pid."' ";
    $result=mysql_query($query);

    //if distance < 10000, put id in ranger array
    while($row=@mysql_fetch_assoc($result)){
      //leave rangeCheck off for now
      //$di=dister($row['lla0'],$row['lla1'],$lla0,$lla1);
      //if($di<10000){
      $ranger[]=$row['id'];
    //}
    }
    mysql_free_result($result);
    if(count($ranger)==0){
      $rangerS=''; 
    }else{
      $rangerS=implode(",", $ranger);
    }

    //between rangeChecks get ranger array from js
  }else{
    $rangerS=$_GET['ranger'];  // $rangerS: string(for inserting) 
    $ranger=explode(",",$rangerS); // $ranger: array(for looping)
  }

  //insert new row first time
  if($inserter==1){
    $idb=dbq("INSERT positioner (id,mod0,mod1,mod2,lla0,lla1,lla2,ranger,namely,message,model) 
      VALUES ('".$pid."', '".$mod0."', '".$mod1."', '".$mod2."', '".$lla0."', '".$lla1."', '".$lla2."', '".$rangerS."', '".$namely."', '".$message."', '".$dbMi."');");

  }else{
    //update the database with current model data and result of range check
    $udb=dbq("UPDATE positioner SET mod0 = '".$mod0."', mod1 = '".$mod1."', mod2 = '".$mod2."', lla0 = '".$lla0."', lla1 = '".$lla1."', lla2 = '".$lla2."', ranger = '".$rangerS."', namely = '".$namely."', message = '".$message."', model = '".$dbMi."' WHERE id = '".$pid."' LIMIT 1;");
  }

  header("Content-type: text/xml");
  echo '<markers>';
  echo '<marker ranger="'.$rangerS.'" pid="'.$pid.'" />';

  //loop through a number of times equal to number of id's in ranger array
  foreach($ranger as $rang){
    $query="SELECT mod0, mod1, mod2, lla0, lla1, lla2, namely, message, model FROM positioner WHERE id = '".$rang."' ";
    $result=mysql_query($query);
    while ($row=@mysql_fetch_assoc($result)){

      echo '<marker mod0="'.$row['mod0'].'" />';       
      echo '<marker mod1="'.$row['mod1'].'" />'; 
      echo '<marker mod2="'.$row['mod2'].'" />'; 
      echo '<marker lla0="'.$row['lla0'].'" />';     
      echo '<marker lla1="'.$row['lla1'].'" />'; 
      echo '<marker lla2="'.$row['lla2'].'" />'; 
      echo '<marker namely="'.rawurlencode(stripslashes($row['namely'])).'" />';
      echo '<marker message="'.rawurlencode(stripslashes($row['message'])).'" />';
      echo '<marker dbMi="'.$row['model'].'" />';  
    }
  }

  echo '</markers>';

} //end if unLoader

//function for calculating distance between latlon pairs, for range check
/* not necessary for only a few visitors
function dister($lat1,$lon1,$lat2,$lon2){
  $R=6378100;
  $lat1*=pi()/180; 
  $lon1*=pi()/180;
  $lat2*=pi()/180; 
  $lon2*=pi()/180;
  $dLat=$lat2-$lat1;
  $dLon=$lon2-$lon1;
  $a=sin($dLat/2)*sin($dLat/2)
    +cos($lat1)*cos($lat2)*
    sin($dLon/2)*sin($dLon/2);
  $c=2*atan2(sqrt($a),sqrt(1-$a));
  $di=$R*$c;
  $di=round($di,6); 
  return $di;        
}
*/
?>

【问题讨论】:

  • 很多脚本,很多可能性,你必须自己做一些基本的调试
  • 那里还有一个 SQL 注入漏洞。您的数据库没有更新这一事实是非常幸运的。
  • 我看到其中至少有两个 @ 错误静音运算符。删除它们,然后将这两个语句放在脚本的最顶部并尝试再次访问它:ini_set('display_errors', true); error_reporting(-1); 如果你没有看到错误,我会很惊讶。

标签: php javascript mysql database


【解决方案1】:

一些笔记。

  • “如果还没有分配 pid”块是悲剧性的。您正在获取表格的全部内容,然后逐行检查是否找到了正确的内容。代码盲目地假设在选择下一个 pid 时,行数将与 id 列匹配。正确的做法(对于 MySQL)是使用自动增量列,这样您就不必担心这种混乱。
  • 您的DELETE FROM 查询包含SQL Injection vulnerability。如果pid 不是字符串'false',它将永远不会被验证。有人可以破坏整个positioner 表。你如何防范它?嗯...
  • 您正在使用addslashes。这不是代码smell,而是代码恶臭。在整个计算历史中,addslashes 从来没有正确使用过*。我认为您正在寻找一种 real 数据库转义机制。因为你使用的是残暴的“mysql”接口,所以你想要mysql_real_escape_string
  • lla1lla2?这些是您能想出的最好和最具描述性的列名称吗?我将假设这些是纬度/经度对。
  • 再一次,SELECT 中存在 SQL 注入。
  • 在那个INSERT 中,你可能盲目地信任$rangerS。 SQL 注入啊!
  • UPDATE
  • 我还想对字符串'true' 和字符串'false' 进行简短的吐槽,但这些都来自糟糕的Javascript。考虑将它们提交为10。另外,请考虑使用像 jQuery 这样的现代 Javascript 库,而不是滚动您自己的 Ajax 位。这将节省您的时间和压力。

认为这里的核心问题实际上是最初的pid 检查。我敢打赌你总是得到一个新的或不正确的@987654342 @ 从表中返回,因为 id 不太可能完全匹配行数。然后,您将使用“新”pidINSERT 进行盲目的无错误检查,但如果您的索引设计正确,则会因重复键错误而失败。因此,没有更新。 但这只是猜测。除了这里的漏洞,我不确定我是否完全理解发生了什么,我没有发现任何明显不正确的地方。

这里还有另一个可能的问题。我将假设pid 表示上下文中的玩家ID。您的代码盲目相信请求来自拥有pid的玩家,但任何人都可以在这里提出请求any 有效的pid 并因此为人们采取行动。我不确定你是不是故意的。

* 好吧,也许有人发现addslashes 有用一两次...

【讨论】:

  • @Pointy:很高兴提供娱乐价值。我已经澄清了我对核心问题的猜测,但我们需要更多地了解数据库才能确定。我不知何故希望我们永远不会知道。
  • 很难从简短的在线书面信息中判断态度,但我向您保证,我是认真的,一点也不讽刺。我投了赞成票,希望我能这样做 10 次。这就是使该网站有价值的答案。
  • @Pointy,没有讽刺意味!虽然这可能是使 SO 有价值的答案类型,但偶尔提出这个问题的方式让我想从轨道上删除该站点。我认为至少在一个有趣的问题上付出努力可能是值得的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 2021-09-10
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多