0

ねえ、私はPHPを初めて使用するので、私がどのようにプログラミングしているかについての洞察を本当に望んでいます。また、セッションの問題の解決策を思い付くのに苦労しています。

私は物々交換およびローカルトレードシステム(LETS)のスクリプトを作成しており、現在、ユーザーがオファー中のすべての製品/サービスを表示し、製品/サービスをクリックして詳細を表示できるオファーページをコーディングしています。製品/サービスをクリックすると、彼らは入札することができます。LETSシステムでは、メンバーは他の人と取引することで稼ぐことができるタイム/ライフドルを持っています。(政府が使用している現在の法定通貨システムとは異なり)仕事をしている人々から作成された代替通貨のほとんどです。したがって、ユーザーがライフドルを持っている場合、製品/サービスを提供している他のユーザーに入札することができます。

私はこれをすべて、と呼ばれる1つのPHPページで実行していますoffers.php。簡単に言えば、で作られた4ページがありoffers.phpます。ユーザーが最初にオファーセクションを表示すると(offers.php)、すべてのオファーが表示されます。次に、オファー(offers.php?id=X)をクリックし、クリックして入札(offers.php?id=X&action=makebid)を行い、入札を確認(offers.php?id=X&action=confirm)します。

さて、私のセッションの問題はこれです:ユーザーが最初からoffers.php?id=X最後までセッションは機能します。彼らがルートを進んだ場合、問題はないと思われ、私の検証をバイパスすることはできません。ただし、ユーザーが「say」offers.php?id=100をクリックしてからブラウザーのアドレスバーにURLoffers.php?id=200&confirmを入力すると、検証をバイパスして、オファーを2回入力することができます(既にオファーを行っている場合)。ユーザーが他のユーザーに直接アクセスした場合も同じことが起こりますoffers.php?etcURLですが、それはそれほど問題ではありません。商品/サービスのページが別のウェブサイトに貼り付けられるのではないかと心配しているので、これを修正したいと思います。そうすると、セッションが正しく機能しなくなります。私が言っていることは意味がありますか?必要に応じて詳しく説明できます。私はプログラミングが大好きなので、できる限りのヒントや課題を捨ててください。時間を割いていただきありがとうございます:)

これが私の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
4

3 に答える 3

2

これは複雑なハハです。

さて、サイトを「ハッキング」する能力を減らす簡単な方法の1つは、「get」変数ではなく「post」変数を使用することです。そうすれば、アドレスバーを変更するだけでなく、変数を投稿する必要があります。

私が行う方法は、「トランザクション」をデータベースに保存することです。したがって、列を含むテーブルとそれに類似したテーブルがsession_idあります。action次に、クエリ文字列から現在の場所を取得する代わりに、スクリプトの各「ページ」をロードするときに、データベースにsession_idを照会し、そこからアクションを取得します。次に、アクションを完了するたびに、データベースを更新して、現在の時点を示します。

これを行う別の方法は、アクションを$ _SESSION変数に入れて、毎回呼び出すことです。

于 2010-08-13T19:09:27.560 に答える
1

私はあなたの質問を速読し(それはいくつかの主要な編集が必要です)、私に飛び出したのは...

私はこれらすべてをoffers.phpという1つのPHPページで実行しています。簡単に言うと、offers.phpで作成された4ページになります。ユーザーが最初にオファーセクション(offers.php)を表示すると、すべてのオファーが表示され、次にオファーをクリックして(offers.php?id = X)、クリックして入札することができます(offers.php?id = X&action = makebid)、次に入札を確認します(offers.php?id = X&action = confirm)。

1つのスクリプトにこれだけ多くの機能があることは、コードの臭いが大きいと言えます。

代わりに4つのPHPスクリプトを用意してみませんか?

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

補遺

@Thomas Claytonが言うように、POSTここでいくつかのリクエストを使用する必要があります。GET教科書の悪いリクエストでサーバーの状態をさまざまな方法で変更しているので、代わりに正規表現を使用してHTMLを解析したいと思います。(これも悪いでしょう)

GETが安全な方法である方法については、ウィキペディアとw3cWebサイトを参照してください。

GETリクエストの状態が変化したためにバグが発生したWebサイトについて読んでください。

于 2010-08-13T19:08:30.830 に答える
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を見つけ、確認を押すことができる場合は、それとアドレスバーに手動で入力することの違いは何でしょうか。アカウントにのみ影響する限り、セキュリティ上の大きな問題ではありません。

コメントの1つで述べたように、より大きな問題は、SQLクエリに挿入する前にIDをエスケープしないことで、招待しているSQLインジェクションです。あなたが次のようなことをしたとしても:

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

悪意のあるテキストではなく、番号があることを確認するため。

考慮すべきもう1つのことは、ifの代わりにswitchステートメントを使用することです。アクションに基づいて切り替えを行います。はるかに読みやすくなります。

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

   'makeoffer':
       // do offer stuff
       break;

   default:
      default stuff

}
于 2010-08-13T19:17:55.830 に答える