私たちは最近APIの作業を開始しましたが、私は哲学の問題に直面しています。これは私が取り組んだ2番目のAPIですが、単一のモデルを取得するために見た標準は常にGETであり、エンドポイントはapi/model/1
のようなもので、1がIDです。ただし、私の同僚は、URLを介してデータを渡さないことを強く求めており、代わりにPOSTを使用し、本文を介してIDを送信したいと考えています。彼の理由は、それがセキュリティリスクであると感じているためです。
同時に、彼は1つのPOSTファイルごとの哲学に従いたいと考えています。つまり、UpdateModel、DeleteModel、およびEditModelのファイルが必要です。
私が提案しているのは、この構造に従うことです。
GET /api/Model Get all to-do items
GET /api/Model/{id} Get an item by ID
POST /api/Model Add a new item
PUT /api/Model/{id} Update an existing item
DELETE /api/Model/{id} Delete an item
しかし、彼はこのようなものを提案しています:
GET /api/Model Get all to-do items
POST /api/Model Get an item by ID
POST /api/Model Add a new item
POST /api/Model Update an existing item
POST /api/Model Delete an item
同僚の哲学に私が理解していないことはありますか?
POSTを使用し、実際のリクエストの詳細を本文に入れると「機能する」。少なくとも何も壊れない。HTTPキャッシングを除いて。しかし、その時点で、HTTPを使用する独自のRPCメカニズムを発明しているトランスポートプロトコルであり、REST HTTPを使用するAPIを構築していません。これは基本的な設計上の選択ですが、どちらも有効です。たとえば、GraphQLはこれを正確に使用しますPOST /some-endpoint
メカニズム。
RESTful APIでは、URI/URLはリソースを識別する必要があります。モデルアイテムがアプリケーションのコンテキストで別個のリソースである場合、RESTfulな設計により、そのような各アイテムに個別のURLが与えられます。ただし、全体としてのアイテムのコレクションが、アプリケーションにとって妥当な最も細かい粒度である場合もあります。
データをURLに入れることがセキュリティリスクであるかどうかは、脅威モデルによって異なります。機密データをURLから除外する2つの理由があります。
XSRFの考慮事項も存在しますが、POST要求を要求し、適切なCSPヘッダーを提供することは、より良い応答です。
他のすべての目的では、パスまたはクエリの部分は、POSTリクエストの本文とまったく同じように安全です。たとえば、バックエンドに安全でない直接オブジェクト参照の脆弱性がある場合、これは、 POST本文はそのままURLコンポーネントを介して–やる気のない攻撃者にとっては少し面倒です。
どちらのソリューションも同じです。唯一の変更は、サーバー側コードへのHTMLプロトコルのマッピングです。
そのため、同じコードとアーキテクチャで両方のマッピングを簡単に実装できます。
パスにIDを含めることによるセキュリティリスクは直接的なものではなく、残りのデータのようにエンコードされますが、パスはログに記録されることがよくあります。このようにデータを含めるのは良い考えではありません。
また、おそらく編集および更新リクエストで送信するオブジェクトには、独自のIDがプロパティとして含まれていることにも注意してください。そのため、パスに追加する必要はありません。
クエリパラメータまたはパスを含む取得リクエストは、クライアントがなくてもブラウザで簡単に使用できます。このため、単純なクエリにはこれらを使用します。
ただし、パスではなくクエリパラメータを使用します。これにより、ロギングが簡単になります。メソッドなどを見つけるためにデータを解析する必要はありません。
ここで他の回答に同意しますが、同僚の意見の背後にある理由についても質問したいと思います。
パスパラメータでPOST bodyを使用しても、意味のあるセキュリティは実際には追加されません。パスパラメータをスヌープできれば、リクエストの本文で確実に同じことができます。
さらに、パスパラメータには実際には機密データがありません。これは、あなたの場合にも当てはまります。