想要反馈我的PHP编程和放大器会议建议

时间:2010-08-13 19:00:30

标签: php session feedback

嘿,我是PHP的新手,所以我非常希望您对我的编程方式有所了解,而且我也无法找到会话问题的解决方案。

我正在为易货交易和本地交易系统制作脚本( LETS ),我正在编写优惠页面,用户可以在其中查看所提供的所有产品/服务,然后点击获得更多详细信息的产品/服务。点击产品/服务后,他们可以出价。在LETS系统中,会员有时间/生活美元,他们可以通过与其他人进行交易来赚取收入。所以它的替代货币就是由工作的人创造的(与我们目前政府使用的法定货币制度不同)。因此,如果用户拥有Life Dollars,他们可以向提供其产品/服务的其他用户出价。

我正在一个名为offers.php的PHP页面上做这一切。简而言之,offers.php将有4页。当用户最初查看优惠部分(offers.php)时,他们会看到所有优惠,然后他们可以点击优惠(offers.php?id=X),然后点击进行竞价(offers.php?id=X&action=makebid)然后确认出价(offers.php?id=X&action=confirm)。

好的,我的会话问题是这样的:当用户从offers.php?id=X开始直到结束时,会话有效。如果他们走的路线他们认为应该没有问题,他们将无法绕过我的验证。但是,如果用户点击说offers.php?id=100,然后将网址offers.php?id=200&confirm输入浏览器地址栏,他们就可以绕过我的验证,从而导致要约被输入两次(如果他们已经提出要约)。当用户直接转到另一个offers.php?etc网址时会发生同样的情况,但这不是什么大问题。我仍然想纠正这个问题,因为我担心什么时候将产品/服务页面粘贴到另一个网站上,因为会话无法正常工作。我说的话有意义吗?如果需要,我可以解释更多。我喜欢编程,所以抛弃任何你可以提出的技巧/挑战。感谢您抽出宝贵时间:)

这是我的offers.php代码:

<?php

require_once('startsession.php');
require_once('dbconnect.php');

if (!isset($_SESSION['user_id'])) {
    echo '<p class="login">Please <a href="login.php">log in</a> to access this page.</p>';
    exit();
}

require_once('navmenu.php');

$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

if (isset($_GET['id']) && $_GET['action'] == 'confirm') {

    $adid = $_GET['id'];
    $userid = $_SESSION['user_id'];
    $cost = $_SESSION['cost'];
    $sellerid = $_SESSION['seller_id'];

    //Check if bid was already made
    $query = "SELECT * FROM transactions WHERE ad_id = '$adid' AND buyer_id = '$userid'";
    $data = mysqli_query($dbc, $query);
    $row = mysqli_num_rows($data);

    if ($row == 1) {
        echo '<p>Bid has been made</p>';
    } else {
        //If bid doesnt already exist insert bid
        $query = "INSERT INTO transactions (ad_id, buyer_id, seller_id, cost, status) VALUES ('$adid', '$userid', '$sellerid', '$cost', 'O')";
        $data = mysqli_query($dbc, $query);
    }
} else if (isset($_GET['id']) && $_GET['action'] == 'makeoffer') {

    $adid = $_GET['id'];
    $userid = $_SESSION['user_id'];

    //Check if bid was already made
    $query = "SELECT * FROM transactions WHERE ad_id = '$adid' AND buyer_id = '$userid'";
    $data = mysqli_query($dbc, $query);
    $row = mysqli_num_rows($data);

    if ($row == 1) {
        echo '<p>You have already made a bid on this..</p>';
    } else {
        echo '<form method="post" action="offers.php?id=' . $adid . '&action=confirm">';
        echo '<p>You are about to bid 5 Life Dollars.';
        echo '<input type="submit" value="Confirm" name="submit" /></p>';
        echo '</form>';
    }
} else if (isset($_GET['id'])) {

    $userid = $_SESSION['user_id'];

    //Get ad details
    $adid = $_GET['id'];

    $query = "SELECT * from ads WHERE id = '$adid'";
    $data = mysqli_query($dbc, $query);

    $row = mysqli_fetch_array($data);

    //echo ad details
    echo '<p>' . $row['ad_name'] . '<br>' . $row['ad_desc'] . '<br>' . 'Cost: ' . $row['timedollars']
    . ' Time Dollars . ' . '<br>';

    //Set session seller and cost
    $sellerid = $row['seller_id'];
    $_SESSION['seller_id'] = $sellerid;
    $_SESSION['cost'] = $row['timedollars'];

    //Check to see if a bid was already made
    $query = "SELECT * FROM transactions WHERE ad_id = '$adid' and buyer_id = '$userid'";
    $data = mysqli_query($dbc, $query);
    $row = mysqli_num_rows($data);

    if ($row == 0 && $userid != $sellerid) {
        echo '<a href="offers.php?id=' . $adid . '&action=makeoffer">Make Bid</a></p>';
    } else if ($row == 1) {
        echo 'Already bidded';
    }
} else {

    //Get all ads/offers
    $query = "SELECT * FROM ads WHERE ad_type = 'O'";
    $data = mysqli_query($dbc, $query);

    //echo all ads
    while ($row = mysqli_fetch_array($data)) {
        echo '<p>' . '<a href="offers.php?id=' . $row['id'] . '">' . $row['ad_name'] . '</a>' . '<br>' . $row['ad_desc'] . '</p>';
    }
}

mysqli_close($dbc);
?>

enter code here

3 个答案:

答案 0 :(得分:2)

这很复杂哈哈。

好的,所以减少“破解”网站的能力的一种简单方法是使用“post”变量而不是“get”变量。这样他们就不能只修改地址栏,他们必须发布他们的变量。

我这样做的方法是将“事务”存储在数据库中。因此,您将拥有一个包含session_idaction或类似列的表格。然后,当他们加载脚本的每个“页面”而不是从查询字符串中获取它们时,您将查询数据库中的session_id并从那里获取操作。然后,每当他们完成一个动作,你就会更新数据库,说明他们现在的位置。

另一种方法是将操作放入$ _SESSION变量并每次调用。

答案 1 :(得分:1)

我快速阅读你的问题(它需要一些主要的编辑),跳出来的东西是......

  

我在一个名为offers.php的PHP页面上完成所有这些操作。简而言之,将有一些由offers.php制作的页面。当用户最初查看商品部分(offers.php)时,他们会看到所有商品,然后他们可以点击商品(offers.php?id = X)然后点击进行出价(offers.php?id = X&amp; action = makebid)然后确认出价(offers.php?id = X&amp; action = confirm)。

我想说在一个脚本中有这么多功能就是主要的代码味道。

为什么不使用4个PHP脚本?

  • offers.php
  • an-offer.php
  • bid.php
  • confirm.php

附录

就像@Thomas Clayton所说,你需要在这里使用一些POST个请求。您正在使用GET请求修改服务器状态,这些请求是教科书 BAD ,因为它让我希望您parsing HTML with RegEx instead。 (这也不错)

请继续阅读Wikipediaw3c web site,了解GET是一种安全的方法。

了解因GET次请求更改状态而导致错误的网站:

答案 2 :(得分:0)

我绝对同意使用POST。类似的东西:

<form method=POST action='offers.php'>
<input type=hidden name=id value=100>
<input type=hidden name=action value=confirm>

</form>

但是,请记住,实际上并没有阻止某人伪造提交内容。只是这样做不太方便。

最后,我会说,如果这是一个用户可以做的动作,我不会花费大量精力来阻止它。也就是说,如果他们可以访问该网站,找到ID 200,并点击确认...好吧,那是什么区别,并手动输入地址栏?只要它只影响他们的帐户,它就不是一个重大的安全问题。

正如我在评论中所说的那样,你更大的问题是你通过在将它们放入sql查询之前没有转义id而邀请的sql注入。即使你做了类似的事情:

$id = $_GET['id'] + 0

确保您拥有号码,而不是恶意文本。

要考虑的另一件事是使用switch语句而不是if。根据操作进行切换。它会更具可读性。

case ($action)
{
   'confirm':
      //do confirm stuff
      break;

   'makeoffer':
       // do offer stuff
       break;

   default:
      default stuff

}