4

私は ASP.net/WinForms アプリを作成した経験があり、簡単なタスク マネージャー プロジェクトを作成して WCF を学習したいと考えています。

受信したテキスト ブロックをお読みいただき、ありがとうございます。私の問題は、実際のコーディングの問題ではなく、設計の問題です。

私の目標は次のとおりです。

  • タスク/todo リストの管理を目的とする Web サービスを (WCF を使用して) 作成する
  • Web サービスにより、ユーザーはアカウントの登録、新しい To Do リストの作成、To Do リストの他のユーザーとの共有などを行うことができます。
  • Web サービスが機能し、すべてが実装された後、ASP.NET Web サイトをその上に重ねて、バックエンドに Web サービスを使用できるようにしたいと考えています。

現時点では、次のものがあります。

  • Web サービスをホストする 1 つのコンソール アプリケーション
  • Web サービスへの呼び出しに使用される 1 つのコンソール アプリケーション (クライアント) (この方法で Web サービスをテストします)

Web サービス アプリケーションには、次の構成ファイルがあります (問題なく貼り付けられていることを願っています)。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="Tasker_Server.Properties.Settings.TaskerConnectionString"
      connectionString="Data Source=PROPHET\SQLEXPRESS;Initial Catalog=Tasker;Persist     Security Info=True;User ID=sa;Password=stf"
  providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.serviceModel>
    <services>
      <service name="Tasker_Server.TaskerService" behaviorConfiguration="TaskerServiceBehavior">
        <host>
          <baseAddresses>
             <add baseAddress="http://localhost:8000/TaskerTest/Service" />
          </baseAddresses>
        </host>
        <endpoint name="login" address="username" binding="wsHttpBinding"
              bindingConfiguration="Binding1"
              contract="Tasker_Server.ITasker" />
        <endpoint name="reg" address="reg" binding="wsHttpBinding"
              bindingConfiguration="Binding2"
              contract="Tasker_Server.Contracts.IRegister" />
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="Binding1" receiveTimeout="00:20:00">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
        <binding name="Binding2">
          <security mode="None">
            <transport clientCredentialType="None" />
            <message establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="TaskerServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
                                customUserNamePasswordValidatorType="Tasker_Server.CustomValidator, Tasker_Server" />
            <serviceCertificate findValue="localhost"
                            storeLocation="LocalMachine"
                            storeName="My"
                            x509FindType="FindBySubjectName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

そして、次のように Web サービスを開始します。

ServiceHost selfHost = new ServiceHost(typeof(TaskerService));

try {
    selfHost.Open();
    Console.WriteLine("Service is up... (press <ENTER> to terminate)");
    Console.ReadLine();

    selfHost.Close();
}
catch (CommunicationException ce) {
    Console.WriteLine("Exception: {0}", ce.Message);
    Console.ReadLine();
    selfHost.Abort();
}

現時点では、次の 2 つの契約しかありません。

[ServiceContract(Namespace="http://Tasker_Server")]
public interface ITasker {
    [OperationContract]
    string CheckCredentials(string username, string password);
}

[ServiceContract(Namespace="http://Tasker_Register")]
public interface IRegister {
    [OperationContract]
    string RegisterUser(string username, string password, string email);
}

私が達成しようとしたことは次のとおりです。

  1. 安全でないエンドポイントを提供します。クライアントはこれを呼び出してアカウントを登録できます。
  2. ユーザーが「ログイン」してすべての操作を呼び出すことができる、セキュリティで保護されたエンドポイントを提供します (カスタム UserNamePasswordValidator で UserName 認証を使用します)。

私のソフトウェアでは、これらの両方が現在機能しています。セキュリティで保護されていないエンドポイントを介して新しいアカウントを登録でき、クライアントで正しい ClientCredentials を提供することで、セキュリティで保護されたエンドポイントを呼び出すことができます。

私の質問は次のとおりです。

  1. 私が理解していることから、UserName 認証を使用することにより、クライアントが Web サービス メソッドを呼び出すたびに、カスタム バリデーターの Validation メソッドが呼び出されます (これは、DB クエリが毎回実行されて資格情報をチェックすることを意味します。セッションが期限切れになるまで 1 回ログインします)。このように物事を行うことに根本的に何か問題がありますか?

  2. これを管理する別の方法を考えました (そして、ある意味で Web サイトがどのように機能するかをシミュレートします):

    • 「ログイン」に似た操作にのみ、安全なエンドポイント (UserName 認証) を使用します。
    • 資格情報が正しい場合は、新しい GUID を作成してメモリに保存し、ユーザー名とその GUID を関連付けます。
    • その場合、すべての操作で UserName 認証は必要ありませんが、追加のパラメーター (GUID) があります。GUID がメモリ内にあり、ユーザーに関連付けられている場合、操作は許可されます。
    • ログアウト操作は、メモリ内の GUID を破壊します。
    • GUIDがクリアで送信されないように、これに加えてSSLを使用できると思います
    • これは Web サービス セキュリティの目的に反するのでしょうか?

どの方法が良いでしょうか?なぜ?

更新:間違った構成ファイルを追加しました。Web サービスではなく、クライアントからのものでした。正しいものを追加しました。

4

3 に答える 3

2

2は合理的な考えです。これは Window Identity Framework と呼ばれます。

あなたが提案したものとの唯一の本当の違いは、フェデレーション セキュリティ モデルでは、認証がアプリケーションから分離されていることです。WIF では、トークン (GUID) を発行する信頼できる機関に対して認証を行います。トークン内で暗号化されているのは、一連のクレーム (許可された操作) です。クライアントは WCF 呼び出しの一部としてトークンを渡し、クレームはセキュリティ プリンシパルに転送され、突然、アプリケーションは WCF を知らなくてもロール ベースのセキュリティを実行します。

WIF の欠点は、複雑で、立ち上げにかなりの時間がかかることです。

WIF の利点は、セキュリティの専門家によって書かれていることです。お金や機密データを処理する商用アプリケーションを実際に構築している場合は、この理由だけで WIF を使用する必要があります。

これは古い記事ですが、アイデアへの良い動機です。そして、MSDNがあります。

于 2012-05-23T07:38:32.450 に答える
2

GUID を使用したアプローチは適切です。他の質問WCFチケットベース認証と参照された投稿を参照してください

WCF カスタム メッセージ ヘッダー

更新: アプローチの比較。

最初のアプローチの利点は、個々の操作のステートレス/セッションレスです。クライアントもサービスも、以前の認証呼び出しの詳細を覚えておく必要はありません。ただし、同じクライアントが複数の呼び出しを行う場合は、毎回ユーザー名とパスワードを覚えて送信するよりも、チケットを覚えておく方が適切です。データベースへの繰り返し呼び出しが心配な場合は、データベース呼び出しを行う前に、しばらくの間 (たとえば 30 分) ユーザー名とパスワード (またはそれらのより良いハッシュ) をキャッシュし、キャッシュされた辞書で新しい要求の詳細を比較できます。

2 番目のアプローチでは、クライアントで状態 (つまり、チケット) を保持する必要があるため、少し複雑になります。ただし、セッション全体でユーザー名とパスワードを覚えておく必要がないため、より安全です。シナリオでは、チケットアプローチをお勧めします。

ちなみに、ログイン後も引き続き https を使用することをお勧めします (通常、パフォーマンスの低下は必須ではありません) が、ネットワーク スニファーがチケットを盗み、それを使用してユーザーの代わりに悪意のあるアクションを実行することを防ぎます。

于 2012-05-22T21:34:17.280 に答える
0

WCF でセッションを使用して目的を達成しませんか?

于 2012-05-22T21:40:54.187 に答える