web-dev-qa-db-ja.com

GETリクエストがサーバー上のデータを変更しないのはなぜですか?

インターネット全体で、私は次のアドバイスを見ます:

GETがサーバー上のデータを変更することはありません-POSTリクエストを使用してください

このアイデアの根拠は何ですか?

データベースにデータを挿入するphpサービスを作成し、GETクエリ文字列にパラメーターを渡すと、なぜそれが間違っているのですか? (SQLインジェクションを処理するために、準備済みステートメントを使用しています)。 POSTリクエストは何らかの方法でより安全ですか?

それともこれには歴史的な理由がありますか?もしそうなら、このアドバイスは今日どのくらい有効ですか?

115

これはアドバイスではありません。

GETHTTPプロトコル でこのように定義されています。 べき等 および 安全 であると想定されています。

理由は-GETをキャッシュして、ブラウザで更新できます。何度も何度も。

つまり、同じGETをもう一度作成すると、データベースに挿入されますagain

GETがリンクになり、検索エンジンによってクロールされる場合、これが何を意味するかを検討してください。重複したデータでデータベースがいっぱいになります。

RI、アドレス指定可能性、およびHTTP GETおよびPOSTの使用 もお勧めします。


一部のブラウザでは link prefetching の問題もあります。ページの作成者からの指示がない場合でも、ブラウザはプリフェッチリンクを呼び出します。

たとえば、ログアウトがサイトのすべてのページからリンクされている「GET」の背後にある場合、この動作だけで他のユーザーがログアウトする可能性があります。

187
Oded

各HTTP動詞には独自の責任があります。たとえば、 [〜#〜] rfc [〜#〜] によって定義されるGET

は、Request-URIで識別される情報(エンティティーの形式)を取得することを意味します。

一方、POSTは、挿入またはより正式な意味です。

POSTメソッドは、オリジンサーバーが
リソースの新しい下位としてリクエストに含まれるエンティティ
Request-LineのRequest-URIで識別

このように維持する理由:

  • 非常にシンプルで、1991年以降、世界のインターネット規模で機能します
  • 単一責任の原則に固執する
  • 他の当事者はGETを使用して、情報の取得およびデータマイニングの手段として機能します
  • GETは、リソースの状態を変更しないsafe操作であると見なされます
  • セキュリティ上の考慮事項、GETは事実上readですが、POSTは事実上書き込み
  • GETは、ブラウザー、ネットワーク内のノード、インターネットサービスプロバイダーによってキャッシュされます。
  • コンテンツが変更されない限り、同じURLへのGETは、同じ結果をすべてのユーザーに返す必要があります。

完全性と正しい使用法を強制するために (source)

  • GETパラメータはURLの一部として渡されます。URLはデフォルトで256文字の限​​られた長さで、一部のサーバーは4000文字以上をサポートしています。長いレコードを挿入したい場合、このデータを渡す正当な方法はありません
  • ときに使用したセキュアな接続、̶などTLS、̶URLではないなって暗号化された、̶したがってすべてザパラメータ̶G̶E̶T̶̶̶a̶r̶e̶̶t̶r̶a̶n̶s̶f̶e̶r̶r̶e̶d̶̶p̶l̶a̶i̶n̶̶t̶e̶x̶t̶。 URLは実際にはTLSで暗号化されているため、TLSは問題ありません。
  • GETを使用してバイナリデータまたは非ASCII文字を挿入することは現実的ではありません
  • GETは、ユーザーがブラウザーの[戻る]ボタンを押すと再実行されます
  • 古いクローラーの中には、?サインイン
24
oleksii

編集:以前、私はPOSTはCSRFからあなたを守るのに役立ちますが、これは間違っています。これは正しく考えていませんでした。変更するには、すべてのリクエストにセッションスコープの一意の非表示トークンが必要です。 CSRFから保護するデータ。

インターネットの初期には、ブラウザアクセラレータがありました。これらのプログラムは、ページ上のリンクをクリックしてコンテンツをキャッシュし始めます。 Google Web Accelerator は、これらのプログラムの1つでした。これは、リンクをクリックしたときに変更を加えるアプリケーションに大混乱をもたらす可能性があります。アクセラレータソフトウェアを使っている人はまだいると思います。

プロキシサーバーとブラウザはGETリクエストをキャッシュするため、ユーザーが再度ページにアクセスすると、リクエストがアプリケーションに送信されない可能性があるため、ユーザーはアクションを実行したと考えますが、実際には実行しませんでした。

10
Sarel Botha

データベースにデータを挿入するphpサービスを作成し、GETクエリ文字列にパラメーターを渡すと、なぜそれが間違っているのですか?

最も単純な答えは「それはGETが意味するものではないためです。」

GETを使用して更新用のデータを渡すのは、ラブレターを書いて「特別オファー-今すぐ行動する!」とマークされた封筒に入れて送るようなものです。どちらの場合も受信者や仲介者がメッセージを誤って処理することに驚かないでください

8
Nathan Long

データベース中心のアプリケーションでの [〜#〜] crud [〜#〜] 操作には、次のスキーマを使用します。

読み取り操作にHTTP GETを使用する(SQL SELECT)

更新操作にHTTP PUTを使用する(SQL UPDATE)

作成操作(SQL INSERT)にはHTTP POSTを使用します

削除操作にHTTP DELETEを使用する(SQL DELETE)

5
user83191

GETがサーバー上のデータを変更することはありません-POSTリクエストを使用してください

そのアドバイス、そしてここでのすべての答えは間違っています。明らかに私は過度に劇的です、他の答えは素晴らしいですが、正確なアドバイスは次のように与えられるべきだと思います:

GETはまれにサーバー上のデータを変更します-そのためにPOSTリクエストを使用します

「絶対にしない」と言うのは極端すぎるため、ここでの他の回答は「まれに」行う理由を正確に説明していますが、GETでデータを変更することが完全に合理的であるシナリオがいくつかあります。一例は、使い捨てのメール確認リンクです。通常、これらのリンクにはGUIDが含まれます。アクセスするとデータを変更する必要があります。正しく実装されている場合、後続の同一のGET要求は無視されます。

これは明らかにEdgeのケースですが、確かに注目に値します。

0
TTT