7

Columns というコレクション リソースがあります。GETwithAccept: application/json は collection を直接返すことができないため、私の表現ではそれをプロパティにネストする必要があります:-

{ "propertyName": [
   { "Id": "Column1", "Description": "Description 1" },
   { "Id": "Column2", "Description": "Description 2" }
  ]
}

質問:

  1. 上記の識別子propertyNameに使用するのに最適な名前は何ですか? それは次のとおりです。

    • d (つまり、dは確立された規則ですか、それとも特定のフレームワーク ( MS WCFおよびMS ASP.NET AJAX ?) に固有のものですか?)
    • 結果(つまり、結果は確立された規則ですか、それとも特定の仕様 ( MS OData ) に固有のものですか?)
    • (つまり、最上位のプロパティには明確な名前を付ける必要がありapplication/json、メディア タイプとしてジェネリックを使用することを明確にするのに役立ちます)

    NB @tuespetreで指摘されているように、XMLまたはその他の表現では、とにかくある程度ラップする必要があります。

  2. コンテンツを PUT するときに、そのプロパティで同じラッピングを保持する必要があります [セキュリティ上の理由から実際には必要ではなく、おそらく従来の JSON の使用法では、PUT と POST を保護する必要がないため、そのようなネストを削除する必要がある場合があります。スクリプト攻撃に対して] ?

    私の腸は、他のすべての表現と同様に対称的であるべきだと言っていますが、d / *結果**を削除するための先行技術があるかもしれません[それがパート1への答えであると仮定して] *

    ...または、PUT-back (または POST) でラッピング プロパティの必要性をなくし、次のようにする必要があります:-

    [
           { "ID": "列 1", "説明": "説明 1" },
           { "ID": "列 2", "説明": "説明 2" }
     ]
    
    • 追加したい場合、ルートレベルのメタデータはどこに行くのでしょうか?
    • POST を作成する人は、それが対称である必要があることをどのように知っているのでしょうか?

編集:JSON を使用したクライアントの使用への影響を具体的に考慮した、合理的な根拠を持つ回答に特に興味があります。たとえば、HALは、両方のターゲット表現にとって意味のあるバインディングを定義するように注意します。

編集 2:まだ承認されていません。なぜですか? これまでの回答には、検索を行ってトップ 20 のヒットから妥当と思われるものを選んでいる私よりも目立たせるような引用や何かがありません。私はうるさいですか?私はそうだと思います(または、適切に質問できない可能性が高いです:D)。1 週間と 3 日間、(確かにわずかな) ボーナスがオンになっていても、まだ 123 ビューしか得られないことに少し腹を立てています (そのうち 3 つの回答は悪くありません)。

4

3 に答える 3

3

更新された回答

あなたの質問に答えて(私の最初の答えで少し接するのとは対照的に:D)、ここに私の意見があります:

1) これに関する私の主な意見は、嫌いだということdです。API を使用するクライアントとして、私は混乱を招くと思います。とにかくそれは何の略ですか?データ?

他のオプションは良さそうです。Columnsユーザーが要求したものをユーザーにミラーバックするため、優れています。

ページネーションを行っている場合、別のオプションは、コレクションのコンテンツ全体を受け取っていないことをクライアントに明らかにするようpageなものかもしれません。slice

{
    "offset": 0,
    "limit": 100,
    "page" : [
        ...
    ]
}

2) TBH、どちらの方法で行ってもそれほど大きな違いはないと思いますが、もし私だったら、封筒を返送する必要はないと思うので、おそらく気にしません (参照)。以下) そして、なぜ要求構造を必要以上に複雑にするのでしょうか?

封筒を返送するのはおかしいと思います。POST はアイテムをコレクションに追加できるようにする必要があるのに、なぜクライアントはこれを行うためにエンベロープをポストする必要があるのでしょうか?

エンベロープを PUT バックすることは、コレクション全体に関連付けられたメタデータを更新していると見なすことができるため、RESTful の観点からは理にかなっています。エンベロープで公開するメタデータの種類について考える価値があると思います。このエンベロープにうまく収まると思われるすべてのもの (ページネーション、集計、検索ファセット、および同様のメタデータなど) はすべて読み取り専用であるため、クライアントがこれをサーバーに送り返すことは意味がありません。クライアントが変更できるエンベロープに大量のデータがあることに気付いた場合は、そのデータをリストをサブコレクションとして別のリソースに分割する兆候である可能性があります。ごみの例:

/animals

{
    "farmName": "farm",
    "paging": {},
    "animals": [
        ...
    ]
}

次のように分割できます。

/farm/1

{
    "id": 1,
    "farmName": "farm"
}

/farm/1/animals

{
    "paging": {},
    "animals": [
        ...
    ]
}

注: この分割があっても、 FacebookLinkedIn のフィールド展開構文などを使用して、両方を組み合わせて 1 つの応答として返すことができます。例えばhttp://example.com/api/farm/1?field=animals.offset(0).limit(10)

クライアントが POST および PUT する JSON ペイロードがどのように見えるべきかをクライアントがどのように知る必要があるかについての質問に応えて、これは API ドキュメントに反映されている必要があります。これに適したツールがあるかどうかはわかりませんが、Swaggerは、 JSON スキーマを使用してリクエスト本文がどのように見えるべきかを文書化できる仕様を提供しています。スキーマを定義する方法についてはこのページを、方法についてはこのページを確認てください。それらを type のパラメーターとして参照します。残念ながら、Swagger はまだ洗練された Web UI でリクエスト ボディを視覚化していませんが、オープン ソースであるため、これを行うための何かをいつでも追加できます。 body

元の回答

そのページのディスカッション スレッドにあるWilliam のコメントを確認してください。彼は、エクスプロイトを完全に回避する方法を提案しています。つまり、応答のルートで JSON 配列を安全に使用できるため、どちらの質問についても心配する必要はありません。

リンク先のエクスプロイトは、Cookie を使用してユーザーのセッションを認証する API に依存しています。代わりにクエリ文字列パラメーターを使用するだけで、エクスプロイトを削除できます。API での認証に Cookie を使用することはあまり RESTful ではないため、おそらくこれを行う価値があります。クライアントの一部は Web ブラウザーではなく、Cookie を処理したくない場合があります。

なぜこの修正が機能するのですか?

エクスプロイトは CSRF 攻撃の一種であり、攻撃者がscript自分のページのタグを API の機密リソースに追加できることに依存しています。

<script src="http://mysite.com/api/columns"></script> 

被害者の Web ブラウザーは、保存されているすべての Cookiemysite.comをサーバーに送信します。サーバーには、これが正当な要求のように見えますsession_id。Cookie (またはサーバー側のフレームワークが Cookie を呼び出すもの) を確認し、ユーザーが認証されていることを確認します。リクエストは次のようになります。

GET http://mysite.com/api/columns
Cookie: session_id=123456789;

API を変更して Cookie を無視し、代わりに session_id クエリ文字列パラメーターを使用すると、攻撃者は被害者の Web ブラウザーをだまして API に session_id を送信させることができなくなります。

有効なリクエストは次のようになります。

GET http://mysite.com/api/columns?session_id=123456789

JavaScript クライアントを使用して上記のリクエストを行う場合、Cookie から session_id を取得できます。他のドメインの Cookie を取得できないため、別のドメインの JavaScript を使用する攻撃者はこれを行うことができません (こちら を参照)。

現在、問題を修正し、session_id Cookie を無視しています。攻撃者の Web サイトのスクリプト タグは、引き続き、次のような GET 行を含む同様のリクエストを送信します。

GET http://mysite.com/api/columns

403 Forbiddenただし、必要な session_id クエリ文字列パラメーターが GET にないため、 サーバーは a で応答します。

この API でユーザーを認証していない場合はどうなりますか?

ユーザーを認証していない場合、データを機密にすることはできず、だれでも URI を呼び出すことができます。CSRF 攻撃を防いだとしても、認証がなければ、攻撃者は API サーバー側を呼び出してデータを取得し、好きなように使用できるため、CSRF は問題になりません。

于 2012-09-26T20:45:48.673 に答える
2
  1. リソースの「エンベロープ」をそのコンテンツから明確に分離するため、「d」を選択します。これにより、消費者は、保持されているものにアクセスする前に、特定のリソースのラッピング プロパティの名前を「推測」するのではなく、応答を解析しやすくなります。

  2. あなたは2つの異なることについて話していると思います:

    • POST リクエストは で送信する必要がありますapplication/x-www-form-urlencoded。応答に新しく作成されたリソースの表現を含めることを選択した場合、応答は基本的に GET を反映する必要があります。(HTTP では必須ではありません)。
    • PUT は確実に GET と対称でなければなりません。PUT 要求の目的は、既存のリソース表現を別のものに置き換えることです。両方のリクエストが同じ規則を共有するのは理にかなっていますね。
于 2012-09-29T18:27:08.750 に答える
1
  1. 意味的に意味があるので、「列」を使用してください。JSONとXMLがどのように相互にミラーリングできるかを考えるのに役立ちます。

  2. コレクションを元に戻す場合は、同じメディアタイプ(構文、形式、これを呼び出すもの)を使用することもできます。

于 2012-09-22T07:00:03.300 に答える