119

ユーザーだけでなく、他の Web サービスやアプリケーションもアクセスする必要がある RESTful Web サービスを設計しています。着信要求はすべて認証する必要があります。すべての通信は HTTPS 経由で行われます。ユーザー認証は、サービスによって提供される/sessionリソースに (SSL 接続を介して) ユーザー名とパスワードを POST することによって取得される認証トークンに基づいて機能します。

Web サービス クライアントの場合、クライアント サービスの背後にエンド ユーザーは存在しません。要求は、スケジュールされたタスク、イベント、またはその他のコンピューター操作によって開始されます。接続するサービスのリストは事前にわかっています (当然だと思います)。他の (Web) サービスからのこれらのリクエストをどのように認証すればよいですか? これらのサービスの認証プロセスをできるだけ簡単に実装したいと考えていますが、セキュリティを犠牲にすることはありません。このようなシナリオの標準およびベスト プラクティスは何でしょうか?

私が考えることができる(または私に提案された)オプション:

  1. クライアント サービスに「偽の」ユーザー名とパスワードを使用させ、ユーザーと同じ方法で認証させます。私はこのオプションが好きではありません - それはちょうど正しく感じられません.

  2. クライアント サービスに永続的なアプリケーション ID を割り当てます。場合によっては、アプリケーション キーも割り当てます。私が理解している限り、これはユーザー名 + パスワードを持つこととまったく同じです。この ID とキーを使用して、各リクエストを認証するか、認証トークンを作成して以降のリクエストを認証することができます。いずれにせよ、アプリケーション ID とキーを入手できる人は誰でもクライアントになりすますことができるため、このオプションは好きではありません。

  3. 前のオプションに IP アドレス チェックを追加できます。これにより、偽のリクエストを実行することが難しくなります。

  4. クライアント証明書。独自の認証局を設定し、ルート証明書を作成し、クライアント サービス用のクライアント証明書を作成します。ただし、いくつかの問題が思い浮かびます: a) 証明書なしでユーザーを認証できるようにするにはどうすればよいですか? b) クライアント サービスの観点から、このシナリオを実装するのはどれほど複雑ですか?

  5. 他に何か - 他の解決策があるはずですか?

私のサービスはJavaで実行されますが、実装の詳細ではなく基本原則に関心があるため、それが構築される特定のフレームワークに関する情報を意図的に省略しました-これに対する最善の解決策は基盤となるフレームワークに関係なく実装できます。ただし、私はこのテーマに少し慣れていないので、実際の実装に関する具体的なヒントや例 (便利なサードパーティ ライブラリ、記事など) も同様に高く評価されます。

4

9 に答える 9

36

あなたの質問を読んだ後、必要なリクエストを行うための特別なトークンを生成してください。このトークンは特定の時間 (1 日としましょう) 存続します。

認証トークンを生成する例を次に示します。

(day * 10) + (month * 100) + (year (last 2 digits) * 1000)

例: 2011 年 6 月 3 日

(3 * 10) + (6 * 100) + (11 * 1000) = 
30 + 600 + 11000 = 11630

次に、「my4wesomeP4ssword!」などのユーザー パスワードと連結します。

11630my4wesomeP4ssword!

次に、その文字列の MD5 を実行します。

05a9d022d621b64096160683f3afe804

いつリクエストを呼び出すか、常にこのトークンを使用し、

https://mywebservice.com/?token=05a9d022d621b64096160683f3afe804&op=getdata

このトークンは毎日常に一意であるため、この種の保護はサービスを常に保護するのに十分すぎると思います.

希望が役立ちます

:)

于 2011-06-03T09:06:03.143 に答える
34

この問題の解決策は、共有秘密に要約されます。また、ハードコードされたユーザー名とパスワードのオプションは好きではありませんが、非常に単純であるという利点があります。クライアント証明書も良いですが、それは本当に大きく異なりますか?サーバーとクライアントに証明書があります。主な利点は、ブルートフォース攻撃が難しいことです。うまくいけば、それを防ぐために他の保護が整っていると思います。

クライアント証明書ソリューションのポイントAを解決するのは難しいとは思いません。ブランチを使用するだけです。if (client side certificat) { check it } else { http basic auth }私はJavaの専門家ではなく、クライアント側の証明書を作成するためにJavaを使用したことはありません。しかし、簡単なグーグルはあなたの路地を真上に見上げるこのチュートリアルに私たちを導きます。

この「何が最善か」という議論のすべてにもかかわらず、「コードが少ないほど、賢さが少ない方が良い」という別の哲学があることを指摘しておきます。(私は個人的にこの哲学を持っています)。クライアント証明書ソリューションは、多くのコードのように聞こえます。

OAuthについて質問があったことは承知していますが、OAuth2の提案には、SSLと組み合わせて使用​​する必要がある「ベアラートークン」と呼ばれる問題の解決策が含まれています。簡単にするために、ハードコードされたユーザー/パス(個別に取り消すことができるようにアプリごとに1つ)または非常によく似たベアラートークンのいずれかを選択すると思います。

于 2011-06-02T16:31:50.537 に答える
11

いくつかの異なるアプローチを取ることができます。

  1. RESTful の純粋主義者は、BASIC 認証を使用し、すべての要求で資格情報を送信することを望んでいます。彼らの理論的根拠は、誰も状態を保存していないということです。

  2. クライアント サービスは、セッション ID を保持する Cookie を保存できます。個人的には、一部の純粋主義者から聞いた話ほど攻撃的ではありません。ただし、このアイデアはあまり好きではないようです。

  3. あなたの説明から、あなたはOAuth2に興味があるように思えます。これまでの私の経験では、私が見たものからすると、それは一種の混乱を招き、ある種の最先端であるということです。そこには実装がありますが、それらはほとんどありません。Java では、Spring3 のセキュリティモジュールに統合されていることがわかりました。(彼らのチュートリアルはうまく書かれています。) Restletに拡張機能があるかどうかを待ち望んでいましたが、これまでのところ、提案されており、インキュベーターにある可能性がありますが、まだ完全には組み込まれていません。

于 2011-05-26T05:40:26.947 に答える
3

クライアント証明書のアプローチに関する限り、クライアント証明書のないユーザーを許可しながら実装することはそれほど難しくありません.

実際に独自の自己署名認証局を作成し、各クライアント サービスにクライアント証明書を発行した場合は、それらのサービスを簡単に認証できます。

使用している Web サーバーによっては、クライアント証明書を受け入れるが必要としないクライアント認証を指定する方法があるはずです。たとえば、Tomcat で https コネクタを指定する場合、「true」または「false」の代わりに「clientAuth=want」を設定できます。次に、自己署名 CA 証明書をトラストストア (デフォルトでは、Web サーバー構成で別のファイルを指定しない限り、使用している JRE の cacerts ファイル) に追加して、信頼できる証明書のみが、自己署名 CA。

サーバー側では、要求からクライアント証明書を取得できる (null でない) 場合にのみ、保護したいサービスへのアクセスを許可し、追加のセキュリティが必要な場合は DN チェックに合格します。クライアント証明書を持たないユーザーは、引き続きサービスにアクセスできますが、要求に証明書が含まれていないだけです。

私の意見では、これは最も「安全な」方法ですが、確かに学習曲線とオーバーヘッドがあるため、ニーズに最適なソリューションであるとは限りません。

于 2011-06-02T21:37:42.093 に答える
3

5. 他に何か - 他にも解決策があるはずですか?

そうです、あります!JWT(JSON Web Token)と呼ばれています。

JSON Web Token (JWT) はオープン スタンダード (RFC 7519) であり、関係者間で JSON オブジェクトとして情報を安全に送信するためのコンパクトで自己完結型の方法を定義します。この情報はデジタル署名されているため、検証および信頼できます。JWT は、秘密鍵 (HMAC アルゴリズムを使用) または RSA を使用した公開鍵と秘密鍵のペアを使用して署名できます。

JWT を調べることを強くお勧めします。代替ソリューションと比較すると、問題に対するはるかに単純なソリューションです。

https://jwt.io/はじめに/

于 2016-05-13T14:08:43.140 に答える
3

私はアプローチを信じています:

  1. 最初のリクエスト、クライアントが ID/パスコードを送信
  2. 一意のトークンの交換 ID/パス
  3. 有効期限が切れるまで、後続の各リクエストでトークンを検証します

実装方法やその他の特定の技術的な詳細に関係なく、かなり標準的です。

本当にエンベロープをプッシュしたい場合は、資格情報が検証されるまでクライアントの https キーを一時的に無効な状態と見なし、そうでない場合は情報を制限し、有効期限に基づいて検証されたときにアクセスを許可することができます。

お役に立てれば

于 2011-05-31T22:04:54.323 に答える
1

サーバーでセッションを作成sessionIdし、各 REST 呼び出しでクライアントとサーバー間で共有できます。

  1. 最初に REST 要求を認証します: /authenticate. sessionId: ABCDXXXXXXXXXXXXXX;を含む応答を (クライアントの形式に従って) 返します。

  2. これsessionIdMap実際のセッションで保存します。Map.put(sessionid, session)またはSessionListenerキーを作成および破棄するために使用します。

    public void sessionCreated(HttpSessionEvent arg0) {
      // add session to a static Map 
    }
    
    public void sessionDestroyed(HttpSessionEvent arg0) {
      // Remove session from static map
    }
    
  3. URL?jsessionid=ABCDXXXXXXXXXXXXXX次のように(または他の方法で) 、すべての REST 呼び出しでセッション ID を取得します。

  4. HttpSessionを使用してマップから取得しますsessionId
  5. セッションがアクティブな場合、そのセッションのリクエストを検証します。
  6. 応答またはエラー メッセージを送り返します。
于 2012-10-05T22:57:46.017 に答える
0

ユーザーがリクエストを承認すると、認証のために他のアプリによって使用される一意のトークンが生成されます。このようにして、他のアプリケーションはユーザー資格情報を処理せず、ユーザーは他のアプリケーションを追加、削除、および管理できます。Foursquare および他のいくつかのサイトはこの方法で認証を行っており、他のアプリケーションとして実装するのは非常に簡単です。

于 2011-05-26T05:34:28.200 に答える
-3

認証の他に、全体像について考えることをお勧めします。バックエンドを認証なしで RESTful サービスにすることを検討してください。次に、非常に単純な認証が必要な中間層サービスをエンド ユーザーとバックエンド サービスの間に配置します。

于 2011-05-26T13:07:09.913 に答える