DBの状態をGETから変更しますか?

addCategory.php

<?php
$parentId = isset($_GET['parentId']) ? $_GET['parentId'] : 0;

$categoryName = $categoryDescription = "";
$fail = "";


if (isset($_POST['submit'])) {  

    if (isset($_POST['categoryName']))
        $categoryName = fix_string($_POST['categoryName']);

    if (isset($_POST['categoryDescription']))
        $categoryDescription = fix_string($_POST['categoryDescription']);

    $hidParentId = $_POST['hidParentId'];
}

$fail  = validate_category_name($categoryName);
$fail .= validate_category_description($categoryDescription);


echo "<html><head><title>An Example Form</title>";

if ($fail == "") {
  echo "success";

    header("Location: processCategory.php?action=add&categoryName=$categoryName&categoryDescription=$categoryDescription&hidparentId=$hidParentId");

    exit;
}

// Now output the HTML and JavaScript code
?>

<!-- The HTML section -->

<script type="text/javascript">
function validate(form)
{

    fail  = validateCategoryName(form.categoryName.value)
    fail += validateCategoryDescription(form.categoryDescription.value)

    if (fail == "") return true
    else { alert(fail); return false }
}
</script></head><body>
<table class="signup" border="0" cellpadding="2"
    cellspacing="5" bgcolor="#eeeeee">
<th colspan="2" align="center">Add Category</th>

<?php

if (isset($_POST['submit'])) {
?>

<tr><td colspan="2">Sorry, the following errors were found
in your form:
<?php echo $fail ?> </td></tr> <?php } ?> <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?parentId=<?php echo $parentId; ?>" onSubmit="return validate(this)"> <tr><td>Category Name</td><td><input type="text" maxlength="32" name="categoryName" value="<?php echo $categoryName; ?>" /></td> </tr><tr><td>Category Description</td><td><input type="text" maxlength="32" name="categoryDescription" value="<?php echo $categoryDescription; ?>" /></td> <input type="hidden" name="hidparentId" value="<?php echo $parentId; ?>" /> </tr><tr><td colspan="2" align="center"> <input type="submit" name="submit" value="ok" /></td> </tr></form></table> <!-- The JavaScript section --> <script type="text/javascript"> function validateCategoryName(field) { if (field == "") return "No name entered.\n" return "" } function validateCategoryDescription(field) { if (field == "") return "No description entered.\n" return "" } </script></body></html> <?php // Finally, here are the PHP functions function validate_category_name($field) { if ($field == "") return "No name entered
"; return ""; } function validate_category_description($field) { if ($field == "") return "No description entered
"; return ""; } function fix_string($string) { if (get_magic_quotes_gpc()) $string = stripslashes($string); return htmlentities ($string); } ?>



processCategory.php

<?php
$action = isset($_GET['action']) ? $_GET['action'] : '';
switch ($action) {

    case 'add' :
        addCategory();
        break;

    case 'modify' :
        modifyCategory();
        break;

    case 'delete' :
        deleteCategory();
        break;

    default :
       //if action is not defined or unknown
       //move to main category page
        header('Location: index.php');
}


/*
    Add a category
*/
function addCategory() {



    $name        = $_GET['categoryName'];
    $description = $_GET['categoryDescription'];
    $parentId  = $_GET['hidparentId'];

    $sql   =  "INSERT INTO tbl_category (cat_parent_id, cat_name, cat_description) 
            VALUES ($parentId, '$name', '$description')";
    $result = dbQuery($sql) or die('Cannot add category' . mysql_error());

    header('Location: index.php?catId=' . $parentId);     

}

function modifyCategory() {

}

function deleteCategory() {

}

?>

Notice here that I get the user inputs thru POST then send that POST data to same .php file......then after validation send those data to another .php file THRU GET.....insert those GET data to the DB then after inserting those data we redirect to another page.

I read that if your changing the state of the database you should use POST not GET. My idea that it is bad because GET data can be seen in the URL so users can change the state of the database in the URL, another is when you click refresh if you use POST then the browser will warn you that your trying to repeat the same method again, BUT if you use GET the browser will not warn you so end up posting the same data twice.

In my code there is no way the user can manipulate the url to change the DB because as soon as the data is inserted we redirect to different page, and also the refresh problem is not a problem here.

I want to a place separated where I process my inputs and that is processCategory.php.

Im a noob please tell me if im dooing right.

1
nl ru de
「私のコードでは、データが挿入されると直ちに別のページにリダイレクトするため、DBを変更するためのURLを操作する方法はありません」というのは非常に危険な考えです。ユーザーはブラウザを制御しており、要求を観察することができます。あなたのWebサーバーは、インターネット上のポート80上のHTTP要求を聞いて応答を吐き出すだけのサーバーです。ユーザーはWebサーバーに必要な要求を行うことができます。また、1つの要求ごとに検証を実行してデータが適切に処理されることを確認するのはサーバーに任されます。
追加された 著者 Yuliy,
注意してください! HTTP GETリクエストは "冪等"でなければなりません。つまり、決して副作用はありません。データを変更することは副作用です。 POSTではGETではなくのみ使用するべきです。
追加された 著者 Charles,
私は情報に感謝を見る
追加された 著者 user1933652,
しかし、私は自分のデータを処理する場所を必要とします。それはprocessCategory.phpです。データをデータベースに挿入する前に、データを同じページにまず検証したいと思います。しかし、ポストリクエストでリダイレクトすることはできません。
追加された 著者 user1933652,

1 答え

どのようにデータがそこに到達するかは問題ではなく、変更することができます。あなたはGETまたはPOSTに入れることができ、ユーザーはそれを改竄したり、独自のリクエストをしたり、途中の誰かがそれを変更する可能性があります(httpsを実行しない限り)。

あなたのスクリプトは、addCategory関数のSQLインジェクションに対して脆弱です。次のように最小限に変更する必要があります。

function addCategory() {
    $name        = mysql_real_escape_string($_GET['categoryName']);
    $description = mysql_real_escape_string($_GET['categoryDescription']);
    $parentId  = mysql_real_escape_string($_GET['hidparentId']);

    $sql   =  "INSERT INTO tbl_category (cat_parent_id, cat_name, cat_description) 
            VALUES ($parentId, '$name', '$description')";
...

Someone could put a part of an SQL query into any of those $_GET (or $_POST...it doesn't matter which) and possibly have it execute on your server. mysql_real_escape_string is a function provided for you so to make sure any parts of queries that may come in to your script by malicious users don't get through. Illustration here: http://xkcd.com/327/

また、より安全なPDOやパラメータ化されたクエリを使用してルックアップすることもできます。

ユーザーが物事を修正して再提出する場合、Noncesを使用することでこれを防ぐことができます。ノンスとは、「 n umberは once 」に使用されるセキュリティのものです。これを行うための簡単な方法は次のとおりです。ユーザーにフォームを表示するときは、データベースに何らかの並べ替えを行い、その数値をフォームの隠しフィールドに配置する必要があります。ユーザーが送信すると、スクリプトはフィールド内のnonceを確認し、データベースに存在するかどうかを確認して削除します。スクリプトがナンスを見つけることができなかった場合、スクリプトは既に使用されていることを知っており、そのリクエストはすでに処理されていたので、ユーザーのリクエストを拒否します。これをさらに安全にするには、ユーザーのIDをデータベースに格納します(ユーザーIDを与える何らかのセッション処理があると仮定します)。各セッションに一意のIDを与え、それをノンスと一緒に使用することは、さらに優れています。このシステムは完璧ではありませんが、ユーザーが誤ってページを更新する場合には少なくとも役立ちます。あなたはそれを "要求ID"と考えることができ、 "要求ID"が処理されると、再度処理することはできません。

繰り返しますが、何らかの方法でデータを検証する限り、データをどこに置いても問題ありません。しかし、1つの制限は、一部のブラウザ(一部のバージョンのIEなど)では2048文字以上のURLを許可しない傾向があることです。 POSTデータは一般的に(PHP自体を除いて)制限されていないので、(POSTのような)データをたくさん送ることを計画しているなら、おそらくPOSTを使いたいでしょう。ごくわずかなデータ(ツイートのような)を送信している場合は、GETを使用することができます。また、パスワードはGET経由で送信されるべきではありません。これは、ユーザーのブラウザがその履歴を保持していて、パスワードがどこでも履歴に浮かび上がることを望まないからです。

編集:あなたのデータを処理するために必ずしも2つの別々のURLを持っている必要はありません。 processCategory.phpからHTML部分を削除することができますが、addCategory.phpの上部にある require processCategory.php を使用し、リダイレクトヘッダーを行う行の代わりに次のように置き換えてください:

addCategory();
header("Location: someSuccessPage.php");

大したことではありませんが、リダイレクトやリクエストが多すぎると、サイトの速度が低下し、サーバーが必要以上に多くのリクエストを処理する可能性があります。 Locationヘッダーを変更するたびに、ユーザーのブラウザーがサーバーから別のURLを要求する302を送信します。

1
追加された
そのLocation:ヘッダーを実行すると、実際にはユーザーのブラウザにそのページに行くように伝えられます。その時点で、誰かがブラウザーにURLを一時停止して変更するように指示し、URLを再び非衛生的にすることができます。経験則は、$ _GETまたは$ _POSTから出てくるものを決して信用しないことです。
追加された 著者 Los Frijoles,
それはすべて優先と慣例です。設定されたルールはありません(しかし、誰もが一方的に議論するでしょう)。私の個人的な好みは、RESTful規約と呼ばれるものに従うことです:GETリクエストはデータベースから物事を取得し、POSTリクエストはデータをポスト(追加)し、PUTは変更を行い、DELETEは削除を要求します。それがどのように働くかを理解している限り、あなたが使用する規則は重要ではありません。また、GETリクエストの場合にのみ、ブラウザの履歴がキャッシュする可能性があるので、履歴ファイルに表示されないようにしてください。
追加された 著者 Los Frijoles,
私はそれがすべてのリダイレクト(意図的な犯罪ではない)でちょっと乱雑だと思っています。違う方法で構造化していきますが、それは私の方法が唯一の方法であるということではありません。それが私の場合は、RESTfulな規約に従うので、データを変更するためにPOSTを使用します。 GETを使用することは悪くありません(また、PHPを使用してビューを追跡する場所によって、GETリクエストでデータベースが変更される場所もあります)。標準でより多くのコードを適合させたい場合は、テンプレートエンジン(Savant3は私のお気に入り)やフレームワーク(CakePHPとDrupalは人気のあるもの)の使用を検討してください。
追加された 著者 Los Frijoles,
データがクエリに反映されている場合は、そのデータをサニタイズする必要があります。それがクエリに入らない場合は、ユーザーに表示されない限り、実際には必要ありません(クロスサイトスクリプティング攻撃を参照)。また、SQLインジェクションでDROPテーブルを実行するだけでなく、クエリやPHP自体に脆弱性が存在すると常に想定しています。 mysql_queryが複数のクエリを実行することができない場合でも、攻撃者はそれをどのようにトリックするかを知ることはできません。
追加された 著者 Los Frijoles,
それはキャラクターからエスケープされているので、それだけで動作するはずです。あなたはいつも試してみることができます。
追加された 著者 Los Frijoles,
私は最初にfix_string()を介してユーザ入力を消毒し、それらのデータが消毒されている場合にそれらのデータをリダイレクトし、なぜ再び消毒するのですか?
追加された 著者 user1933652,
あなたは$ _GETを通してデータベースを操作できると言っていますか?あなたがデータを操作すると、$ _POSTを使うべきだと私は幾分読んでいます。データベースの管理とは、データベースへのデータの挿入と削除を意味します。
追加された 著者 user1933652,
しかし、私は自分のコードが悪いコードであると感じている
追加された 著者 user1933652,
私が落ち着いた大会に従うならば、私は$ _GETから来るデータも浄化すべきですか?データがデータベースの状態を変更しなかったので、なぜそれを消毒するのか? mysql_query()とmysqli_query()は単一のSQL文しか実行できません。 DROP TABLEの学生 - ?仕事はありません。
追加された 著者 user1933652,
データベースの中に「もしあなたが検索すれば」あなたは「あなたは手に入りますか?すみません。
追加された 著者 user1933652,
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

このグループではPHPについて話します。 パートナー:kotaeta.com