11

IIS でホストされ、http トランスポートを使用し、サーバーのメモリに状態を保持する WCF サービスを作成する必要があります。ステートフル サービスが適切でないことは承知していますが、この最後の制約は、サービスをレガシー クライアントで動作させるために必要です。

私の最初の考えは、値を保存するためのasp.netのセッションでした。サービスで asp.net 互換モードを有効にすると、HttpContext にアクセスできるようになりましたが、セッション オブジェクトに配置された値がメモリに保持されませんでした。これは、セッション状態を処理する http モジュールが正しく構成されていなかったことが原因だと思いますが、答えをグーグルで調べたときに、WCF セッションに出くわし、それらを使用する方がよいと考えました。

ただし、WCF セッションは文書化されておらず、サービスに奇妙な一連の前提条件を課しているように見えます。私のニーズに合った構成を見つけることができませんでした。IIS でホストする必要があり、http または https トランスポートを使用する必要があり、クライアントとサーバーが同じドメインの一部ではないため、Windows 認証では応答しません。wsHttpBinding を使用してこれを実行しようとしています。WCF セッションにはセキュリティまたは信頼できるメッセージが必要だと聞いていましたが、 - 標準のバインディングを使用し、サーバーが同じドメインの一部ではない場合、「SecurityNegotiationException The caller」で失敗します。サービスによって認証されませんでした」例外。Windows セキュリティを使用していたので、これはかなり論理的です。

  • セキュリティ コンプリートを無効にすると、「コントラクトにはセッションが必要ですが、バインディング 'WSHttpBinding' はそれをサポートしていないか、それをサポートするように適切に構成されていません。」で失敗します。</p>

  • セキュリティを無効にしたまま信頼できるメッセージを有効にすると、「WSHttpBinding がトランスポート セキュリティ (HTTPS) を介した信頼できるセッションをサポートしていないため、バインディングの検証に失敗しました。チャネル ファクトリまたはサービス ホストを開くことができませんでした。メッセージ セキュリティを使用して、HTTP を介した安全で信頼性の高いメッセージングを実現してください。」</p>

  • トランスポート レベルのセキュリティを有効にしようとしましたが、生成されたエラーに違いはないようです

私に適した構成はありますか? それとも、asp.net セッションを使用する計画に戻る必要がありますか?

4

2 に答える 2

25

非常に簡単な方法で、WCF にセッション情報をメモリに保持させることができます。私の説明では、外的影響の可能性を排除するために、まったく新しいプロジェクトから始めていると仮定します。

  1. 新しい WCF サービス ライブラリ プロジェクトを作成します。このプロジェクトには、WSHttpBidingバインドが事前構成されたサービスが既に含まれています。
  2. サービス コントラクト (IService1.cs) に移動し、ServiceContract 属性を次のように変更します。

    [ServiceContract(SessionMode = SessionMode.Required)]
    
  3. サービスの実装 (Service1.cs) に移動し、次の ServiceBehavior 属性をサービス クラスに追加します ( Service1)。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
    
  4. セッション データをサービス クラスのメンバーとして追加します ( Service1):

    public class Service1 : IService1
    {
        ...
    
        private string UserFullName { get; set; }
    
        ...
    }
    
  5. メンバーを使用して、セッション固有のデータを表示します (サービス コントラクトにも忘れずに追加してくださいIService1)。

    public class Service1 : IService1
    {
        ...
    
        public string Welcome(string fullName)
        {
            UserFullName = fullName ?? "Guest";
            return string.Format("Welcome back, {0}!", UserFullName);
        }
    
        public string Goodbye()
        {
            return string.Format("Come back soon, {0}!", UserFullName ?? "Guest");
        }
    
        ...
    }
    

SessionMode.Requiredクライアントがセッション追跡されるようにします。
InstanceContextMode.PerSessionサービス クラス (Service1) のインスタンスがセッションごとに作成されるため、その中にセッション データを保持でき、同じセッション内の複数の呼び出しにわたってメモリに存在します。
ConcurrencyMode.Single1 つのスレッドのみが各サービス クラス インスタンス (Service1) に入ることができるようにし、サービス クラス (および外部のスレッド セーフな場所) からのデータのみにアクセスする場合に発生する可能性のある同時実行の問題を防ぎます。

編集:デフォルトでWSHttpBindingは、セキュリティ セッションのみを許可します。ただし、信頼できるセッションもサポートしているため、セキュリティを有効にせずにセッションを確立できます。次のバインド構成は、セキュリティを無効にし、信頼できるセッションを有効にします。

<wsHttpBinding>
    <binding name="wsHttpBindingConfiguration">
        <security mode="None" />
        <reliableSession enabled="true" />
    </binding>
</wsHttpBinding>
于 2011-01-22T14:40:19.500 に答える
1

IMOこれは、WCFのようにHTTPを介した抽象化が不十分なテクノロジを使用している場合に発生します。理論的には、WCF WebサービスをHTTPなしで(つまり、NET TCP、MSMQなどを介して)ホストできるという事実により、構成の地獄に入り、「正しい構成を推測する」というゲームを開始せずに、HTTPの組み込み機能を使用することが難しくなります。試行錯誤によって」、機能する正しいものが見つかるまで、考えられるすべての構成順列を試してみてください。

最終的に、WCFを使用できず、Webサービスを最初から実装する必要がある場合は、クライアントが正常に認証されたときにCookieを設定するだけです。次に、すべてのクライアントリクエストで、そのCookieによって参照されるセッション情報を取得します。

WCFを使用する必要がある場合に考えられる解決策の1つは、セッション管理を自分の手で行い(何かを機能させるために必要な作業に不満がある場合に行うことです)、すべてのWebに明示的な「Session」プロパティを設定することです。セッション/認証を必要とするサービス(通常、認証で生成されたGUID)。したがって、後続のリクエストごとに、GUIDを使用して、そのクライアントに関連付けられているセッション情報を再水和します。

さまざまなWebサービスフレームワークを試すことに興味がある場合は、オープンソースのWebサービスフレームワークを維持します。これにより、構成不要のDRYテスト可能なWebサービスを構築でき、作成した各WebサービスにREST経由で自動的にアクセスできます。 XML、JSON、JSV、SOAP 1.1、SOAP1.2エンドポイント。事実上、RESTフルクライアントのHTTP GET URL、簡単なデバッグ、およびSOAPエンドポイント(一部の企業で現在も義務付けられている一般的な選択肢)を介して同じWebサービスにアクセスできます。Hello Worldチュートリアルでは、その機能のいくつかとその動作の概要を説明します。

于 2011-01-22T12:02:15.570 に答える