/ loginまたは/ registerリソースをRESTfulに設計しますか?


122

私はWebアプリを設計していたところ、自分のAPIをRESTful Webサービスとしてどのように設計するべきかについて考えるのをやめました。今のところ、私のURIのほとんどは汎用であり、さまざまなWebアプリに適用できます。

GET  /logout   // destroys session and redirects to /
GET  /login    // gets the webpage that has the login form
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx
GET  /user/xxx // gets and renders current user data in a profile view
POST /user/xxx // updates new information about user

SOとグーグルを探し回った後、私はここでかなり間違っていると感じています。

から始めて/logout、おそらく私は実際にはGET何もしないので、セッションを破棄してリダイレクトするPOSTというリクエストの方が適切な場合があります。そして、用語は留まるべきですか?/logoutGET/logout

何について/login/register。に変更/registerする/registrationことはできますが、サービスに根本的な機能が変更されることはありません。

/userリソースを公開することはありません。たぶんそれはなんとか利用できるでしょう。たとえば、ユーザーを取るmyUser

foo.com/user/myUser

または

foo.com/user

エンドユーザーは、URIに余分な冗長性を必要としません。しかし、どちらが視覚的に魅力的ですか?

このRESTビジネスに関するSOで他のいくつかの質問に気づきましたが、できればここに示したものについてのガイダンスを本当に感謝します。

ありがとう!

更新:

私もいくつかの意見をお願いします:

/user/1

/user/myUserName

回答:


63

特にRESTに対応していないことが1つあります。それは、ログアウトするためのGETリクエストの使用です。

http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methodsから)

一部のメソッド(HEAD、GET、OPTIONS、TRACEなど)は安全であると定義されています。つまり、情報の取得のみを目的としており、サーバーの状態を変更するべきではありません。言い換えれば、ロギング、キャッシング、バナー広告の提供、またはWebカウンターの増加などの比較的無害な影響を超えて、それらに副作用があってはなりません。[...]

[... H]サーバーによる[GETリクエストの] andlingは、いかなる方法でも技術的に制限されていません。したがって、不注意または意図的なプログラミングは、サーバー上で重要な変更を引き起こす可能性があります。これはお勧めできません。Webキャッシング、検索エンジン、その他の自動エージェントで問題が発生する可能性があるためです[...]

ログアウトとリダイレクトに関しては、ログアウトURIに投稿して、303応答をログアウト後のページにリダイレクトさせることができます。

http://en.wikipedia.org/wiki/Post/Redirect/Get

http://en.wikipedia.org/wiki/HTTP_303

URL設計の問題に対処するために編集します。

「リソースをどのように設計しますか?」私にとって重要な質問です。「URLを設計するにはどうすればよいですか?」は、次の2つの領域における考慮事項です。

ユーザーに表示されるURLは、できれば醜く意味のあるものにしないでください。あるリソースへのリクエストでCookieを送信し、他のリソースへは送信しない場合は、パスとCookieパスを構造化する必要があります。

JRandomUser自分のプロファイルを確認したい場合、foo.com/user/JRandomUserまたはURLをやよりもきれいにしたいfoo.com/user/(JRandom's numeric user id here)場合は、ユーザーが自分の情報を確認するためだけに別のURLを作成できます。

GET foo.com/profile /*examines cookies to figure out who 
                     * is logged in (SomeUser) and then 
                     * displays the same response as a
                     * GET to foo.com/users/SomeUser.
                     */

私はこの問題について知恵よりも無知をはるかに容易に主張しますが、ここにいくつかのリソース設計の考慮事項があります:

  1. コンシューマー:ブラウザで直接表示する、XHR経由でロードする、または他の種類のクライアントからアクセスするリソースはどれですか?
  2. アクセス/アイデンティティ:応答はCookieまたは参照元に依存しますか?

1
ありがとうございます。私があなたの個別のURL提案(GET foo.com/profile/)を実装するつもりなら、それはmomoが提案したようにプレゼンテーション層の一部でしょうか?言い換えれば、そのGETリクエストは正確に何を返す必要がありますか?WebページまたはJSONですか?
QCOM

2
ああ、今は見えると思います。モモの答えは本当に物事を片付けました。RESTfulなAPIが複数のプラットフォームにできるように構成されているのでGETPOSTPUT、およびDELETEリソース。Webサイトは、APIにアクセスするもう1つのプラットフォームです。つまり、ウェブサイトのURLのデザインはRESTful APIのデザインとはまったく異なります。私がまだ間違っているかどうか教えてください。
Qcom、2011

はい、REST APIを1セットのURLにし、ウェブサイトを別のセットにします。次に、ページがAPI URLに適切なXmlHttpRequestsを作成してクライアントとして機能するように、ウェブサイトのURLから適切なHTML + JavaScriptが返されます。
ellisbben

129

RESTfulは、URLを構築するためのガイドラインとして使用でき、セッションユーザーリソースを作成できます

  • GET /session/new ログインフォームのあるWebページを取得します
  • POST /session データベースに対して資格情報を認証します
  • DELETE /session セッションを破棄して/にリダイレクトします
  • GET /users/new 登録フォームがあるウェブページを取得します
  • POST /users 入力された情報を新しい/ user / xxxとしてデータベースに記録します
  • GET /users/xxx //プロファイルビューで現在のユーザーデータを取得してレンダリングします
  • POST /users/xxx //ユーザーに関する新しい情報を更新します

これらは複数でも単数でもかまいません(どちらが正しいかわかりません)。私は通常/users(予想どおり)ユーザーインデックスページに使用し、(予想どおり)/sessionsログインしているユーザーを確認します。

番号の代わりにURLで名前を使用する(/users/43vs /users/joe)のは、通常、技術的な要件ではなく、ユーザーや検索エンジンにより親しみやすくしたいという願望が原因です。どちらでもかまいませんが、一貫性を保つことをお勧めします。

register / login / logoutまたはsign(in|up|out)を使用すると、残りの用語ではうまく機能しないと思います。


6
驚くばかり!私はあなたがそれらのリソースを名詞化する方法が好きです。それはかなりきれいです。私が聞いたこと/newから、GET /session/非RESTfulに追加していないのですか?私は、動詞は、通常のHTTP動詞(に委ねられていることを聞いたことがあるGETPOSTなど)。
Qcom

2
@Zach newは動詞ではありません。この場合、それはセッションのサブリソースです。
Kugel 2013

DELETE / sessionで削除するセッションを決定する方法は?CurlはDELETEリクエストでCookieもパラメーターも送信しません。私は仮定します-DELETE / session / sessionIdを使用するだけですか?別の質問は、どのようにPOST / sessionでセッションIDを返すかです。
Tvaroh 2013年

9
確かに安らぎは、自分を不幸にし、まったく重要でないことに時間を費やす方法です。
Jian Chen

6
個人的には、フォーム(/ new)を返すルートを持つことは好きではありません。これにより、ビューとビジネスロジックの分離が崩れます。/新しいルートがなければ、提案されたルートは完璧に見えます。
Scadge

60

セッションはRESTfulではありません

  • はい、知っています。通常はOAuthで行われますが、実際にはセッションはRESTfulではありません。/ login / logoutリソースを使用するべきではありません。主にセッションを使用するべきではないためです。

  • 実行する場合は、RESTfulにしてください。リソースは名詞であり、/ loginと/ logoutは名詞ではありません。/ sessionを使用します。これにより、作成と削除がより自然なアクションになります。

  • セッションのPOST対GETは簡単です。ユーザー/パスワードを変数として送信する場合は、URIの一部としてパスワードを送信したくないので、POSTを使用します。ログに表示され、おそらくネットワーク上に公開されます。また、GET argsの制限でソフトウェアが失敗するリスクもあります。

  • 私は通常、RESTサービスで基本認証または認証なしを使用します。

ユーザーの作成

  • これは1つのリソースなので、/ registerは必要ありません。

    • POST / user-リクエスターがIDを指定できない場合にユーザーを作成します
    • PUT / user / xxx-事前にIDを知っていると想定してユーザーを作成または更新します
    • GET / user-x個のユーザーIDをリストします
    • GET / user / xxx-ID xxxのユーザーの詳細を取得します
    • DELETE / user / xxx-ID xxxのユーザーを削除します
  • 使用するIDの種類は難しい質問です。一意性の強制、削除された古いIDの再利用について考える必要があります。たとえば、IDがリサイクルされる場合(可能な場合)、それらのIDをバックエンドの外部キーとして使用したくない場合。バックエンドの要件を緩和するために、外部/内部ID変換のルックアップを行うことができます。


6
これが最良の答えです。/ loginと/ logoutはリソースではなく、RESTの概念を壊します。
wle8300 2016

5
認証!=セッション
dietbuddha

1
はい、フィールディングの論文はセクション5.1.3で「[s]セッション状態は完全にクライアント上に保持される[...]」と述べています。さらに、理想的には、認証はサーバー側でもステートレスでなければならない、つまり、アクティブな「認証チケット」をデータベースに保存するのではなく、サーバーは認証情報自体に基づいて認証認証情報を検証できる必要があります。たとえば、秘密キーと組み合わせて自己完結型の暗号化トークンを使用する。したがって、/ sessionリソースの代わりに/ authenticationリソースを導入することもできますが、実際には問題も解決されません...
raner

実際、/ loginと/ logoutは名詞です。/ log_inと/ log_outを考えていると思います。
TiggerToo

21

モバイルアプリやサーバー間通信、他の人のためのREST APIの構築に使用されるかどうかに関係なく、クライアント向けのさまざまなREST Webサービスを統合した経験から簡単に説明します。以下は、他の人のREST APIと私たちが自分で構築したものから収集したいくつかの観察です。

  • 私たちがAPIと言うとき、それは通常、プログラミングインターフェイスのセットを指し、プレゼンテーション層は必要ありません。RESTもデータ中心であり、プレゼンテーション主導型ではありません。そうは言っても、ほとんどのRESTはJSONまたはXMLの形式でデータを返し、特定のプレゼンテーションレイヤーを返すことはほとんどありません。この特性(直接のWebページではなくデータを返す)は、マルチチャネル配信を実行するREST機能を備えています。つまり、同じWebサービスをHTML、iOS、Androidでレンダリングしたり、サーバー間の組み合わせとして使用したりすることもできます。
  • HTMLとRESTの両方をURLとして組み合わせることは非常にまれです。デフォルトでは、RESTはサービスとしての考え方であり、プレゼンテーション層はありません。Webサービスを利用するユーザーは、呼び出したサービスのデータを必要に応じてレンダリングする必要があります。その時点で、以下のURLは、これまでに出会ったほとんどのRESTベースのデザイン(FacebookやTwitterから来ているものなどの標準)に準拠していません。
GET / register //登録フォームのあるWebページを取得します
  • 前のポイントから続けて、RESTベースのサービスが以下に提案するようなリダイレクトを行うこともまれです(私はこれに遭遇していません)。
GET / logout //セッションを破棄して/にリダイレクトします
POST / login //データベースに対して資格情報を認証し、新しいセッションでホームをリダイレクトするか、/ loginにリダイレクトします
 

RESTはサービスとして設計されているため、ログインやログアウトなどの機能は通常、成功/失敗の結果(通常はJSONまたはXMLデータ形式)を返し、それをコンシューマーが解釈します。そのような解釈には、あなたが言及したように適切なウェブページへのリダイレクトが含まれる可能性があります

  • RESTでは、URLは実行されるアクションを示します。そのため、できるだけあいまいさをなくす必要があります。異なるアクションを実行する同じパス(/ registerなど)を持つGETとPOSTの両方を使用することはあなたのケースでは正当ですが、そのような設計は提供されるサービスにあいまいさをもたらし、サービスのコンシューマーを混乱させる可能性があります。たとえば、以下で紹介するようなURLはRESTベースのサービスには理想的ではありません
GET / register //登録フォームのあるWebページを取得します
POST / register //入力した情報を新しい/ user / xxxとしてデータベースに記録します

これらは、私が扱ってきた点のいくつかです。参考になると思います。

RESTの実装に関しては、これらは私が遭遇した典型的な実装です:

  • GET / logout  
    

    バックエンドでログアウトを実行し、操作の成功/失敗を示すためにJSONを返します

  • POST /ログイン
    

    資格情報をバックエンドに送信します。成功/失敗を返します。成功すると、通常はセッショントークンとプロファイル情報も返されます。

  • POST /登録
    

    登録をバックエンドに送信します。成功/失敗を返します。成功した場合、通常はログインの成功と同じように扱われます。または、個別のサービスとして登録することもできます

  • GET / user / xxx
    

    ユーザープロファイルを取得し、ユーザーのプロファイルのJSONデータ形式を返す

  • POST / user / xxx 
    //に改名 
    POST / updateUser / xxx
    

    更新されたプロファイル情報をJSON形式で投稿し、バックエンドの情報を更新します。成功/失敗を呼び出し元に返す


3
はい、REST APIをHTMLベースのアプリ(JavascriptおよびAJAXを介して)と統合している場合、JSONはJavascriptによってネイティブに解析されるため、大きなメリットがあります。Android / Javaでは、JSONはXMLに比べて解析が簡単で簡単です。
momo

15
GET / logoutは危険です。GETはべき等でなければなりません。また、ブラウザは<a> hrefsをプリフェッチして、ログアウトします。
Kugel 2013

4

これはRESTfulな認証アプローチだと思います。ログインにはを使用しますHttpPut。このHTTPメソッドは、キーが提供され、繰り返し呼び出しがべき等である場合に作成に使用できます。LogOffの場合、HttpDeleteメソッドで同じパスを指定します。動詞は使用されていません。適切なコレクションの複数化。HTTPメソッドは目的をサポートします。

[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }

[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }

必要に応じて、アクティブをアクティブに置き換えることができます。


1

Twitterに似たユーザーアカウントURLを使用することをお勧めします。ユーザーアカウントのURL foo.com/myUserNameは、https://twitter.com/joelbylerというURLでTwitterアカウントにアクセスできるのと同じようなものです

POSTが必要なログアウトに同意しません。APIの一部として、セッションを維持する場合は、UUID形式のセッションIDを使用して、ユーザーを追跡し、実行されているアクションが承認されていることを確認できます。その後、GETでもセッションIDをリソースに渡すことができます。

簡単に言うと、URLは覚えやすいものにする必要があります。


問題は、APIリソースに関するものです。あなたの答えはプレゼンテーション層についてです。
辺野
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.