2012-09-25 103 views
13

wsHttpBindingsとSSLを有効にしたWCFサービスがありますが、WCFセッションを有効にしたいと思います。WCFでSSL wsHttpBindingを使用してセッションを有効にする方法

必要

SessionMode:=SessionMode.Required 

にSessionModeを変更した後、私は以下のエラーを取得しています。

契約ではセッションが必要ですが、バインディング 'WSHttpBinding'は をサポートしていないか、サポートするように正しく設定されていません。

ここにサンプルアプリケーションがあります。

App.configファイル

<?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 

     <system.web> 
     <compilation debug="true" /> 
     </system.web> 
     <!-- When deploying the service library project, the content of the config file must be added to the host's 
     app.config file. System.Configuration does not support config files for libraries. --> 
     <system.serviceModel> 

     <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
     <client /> 
     <bindings> 
      <wsHttpBinding> 
      <binding name="NewBinding0" useDefaultWebProxy="false" allowCookies="true"> 
       <readerQuotas maxStringContentLength="10240" /> 
       <!--reliableSession enabled="true" /--> 
       <security mode="Transport"> 
       <transport clientCredentialType="None" proxyCredentialType="None" > 
        <extendedProtectionPolicy policyEnforcement="Never" /> 
       </transport > 
       </security> 
      </binding> 
      </wsHttpBinding> 
     </bindings> 
     <services> 
      <service name="WcfServiceLib.TestService"> 
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="NewBinding0" 
       contract="WcfServiceLib.ITestService"> 
       <identity> 
       <servicePrincipalName value="Local Network" /> 
       </identity> 
      </endpoint> 
      <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" /> 
      <host> 
       <baseAddresses> 
       <add baseAddress="https://test/TestService.svc" /> 
       </baseAddresses> 
      </host> 
      </service> 
     </services> 

     <behaviors> 
      <serviceBehaviors> 
      <behavior> 
       <!-- To avoid disclosing metadata information, 
       set the value below to false and remove the metadata endpoint above before deployment --> 
       <serviceMetadata httpsGetEnabled="True"/> 
       <!-- To receive exception details in faults for debugging purposes, 
       set the value below to true. Set to false before deployment 
       to avoid disclosing exception information --> 
       <serviceDebug includeExceptionDetailInFaults="False" /> 
      </behavior> 
      </serviceBehaviors> 
     </behaviors> 
     </system.serviceModel> 

    </configuration> 

ITestService.vb

<ServiceContract(SessionMode:=SessionMode.Required)> 
    Public Interface ITestService 

     <OperationContract(IsInitiating:=True, IsTerminating:=False)> _ 
     Function GetData(ByVal value As Integer) As String 

    End Interface 

TestService.vb

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession, _ 
    ReleaseServiceInstanceOnTransactionComplete:=False, _ 
    ConcurrencyMode:=ConcurrencyMode.Single)> 
     Public Class TestService 
      Implements ITestService 

      Private _user As User 

      <OperationBehavior(TransactionScopeRequired:=True)> 
      Public Function GetData(ByVal value As Integer) As String _ 
Implements ITestService.GetData 

       If _user Is Nothing Then 

        _user = New User() 
        _user.userName = "User_" & value 
        _user.userPassword = "Pass_" & value 

        Return String.Format("You've entered: {0} , Username = {1} , Password = {2} ", _ 
             value, _user.userName, _user.userPassword) 
       Else 
        Return String.Format("Username = {1} , Password = {2} ", _ 
            _user.userName, _user.userPassword) 
       End If 

      End Function 

     End Class 

私はすべてのPOを試し私は見つけることができたが、何も助けなかった。

信頼性の高いセッションを有効にするには、いくつかのアドバイスが、(カスタムバインディングを持っている場合のみ)、それはSSLでは動作しません、他の人のアドバイスは、HTTP代わりのHTTPSを使用するには、私は思います可能なら現在の設定でセッションを有効にすることができます。

これを達成する方法はありますか?

どんな種類のヘルプでも大歓迎です。

+0

wcfサービスでセッション状態を有効にする理由は何ですか?あなたが高いパフォーマンスを求めているなら、これはボトルネックになる可能性があります。セッション状態wcfサービスは避けるべきです。 –

+0

すべてのセッションに_user変数が必要です。すべての呼び出しに対してサービスクラスの新しいインスタンスが取得されます。 _userの値は常にNothingです。 – hgulyan

+0

すべてのクライアントのデータを保存する必要がある場合、私の状況にはどのような解決方法を使用しますか? – hgulyan

答えて

18

「セッション」をwsHttpBindingで使用するには、信頼性の高いメッセージングまたはセキュリティセッションのいずれかを使用する必要があります。 (出典:how to enable WCF Session with wsHttpBidning with Transport only Security)。

WSHttpBindingは、セキュリティ(SecureConversation)または信頼性の高いメッセージングが有効な場合のみ、セッションをサポートします。 トランスポートセキュリティを使用している場合は、WS-SecureConversationを使用せず、WS-ReliableMessagingはデフォルトでオフになっています。したがって、WSHttpBindingがセッションに使用する2つのプロトコルは利用できません。メッセージセキュリティを使用するか、信頼性の高いセッションを有効にする必要があります。 (出典:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/57b3453e-e7e8-4875-ba23-3be4fff080ea/)。

RMセッションを保護する方法はセキュリティセッションを使用する方法であり、Httpsはセッションを提供しないため、標準バインディングでRM over Httpsを許可しませんでした。

ここでは、msdn blurbが見つかりました。http://msdn2.microsoft.com/en-us/library/ms733136.aspx bladは「唯一の例外はHTTPSを使用している場合です。 SSLセッションは信頼できるセッションにバインドされていません。これは、セキュリティコンテキスト(SSLセッション)を共有しているセッションが相互に保護されていないため、脅威になります。アプリケーションに応じて実際の脅威になる可能性もあります。」

しかし、脅威がないと判断した場合は、これを行うことができます。カスタムバインディングhttp://msdn2.microsoft.com/en-us/library/ms735116.aspx(ソース:http://social.msdn.microsoft.com/forums/en-US/wcf/thread/fb4e5e31-e9b0-4c24-856d-1c464bd0039c/)経由のRM over HTTPSサンプルがあります。トランスポート・セキュリティを削除し、

<wsHttpBinding> 
    <binding name="bindingConfig"> 
     <reliableSession enabled="true" /> 
     <security mode="None"/> 
    </binding> 
    </wsHttpBinding> 

信頼性の高いメッセージングを有効にする、wsHttpBindingをしてくださいしかし、あなたはSSL層と、あなたのセキュリティの一部を失う -

1:あなたがいずれかのことができ、あなたの可能性をまとめると

2 - あなたのSSLのセキュリティレイヤを手にするが、あなたのクライアントは、(任意の形式の)資格情報を提供する必要があるとも、あなたならばだろう、wsHttpBindingをキープ​​トランスポート・セキュリティを維持し、メッセージ認証

<wsHttpBinding> 
    <binding name="bindingConfig"> 
     <security mode="TransportWithMessageCredential"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </wsHttpBinding> 

を追加サービス側で検証しないでください。WCFは資格情報を指定していないメッセージを拒否するため、偽のものを提供する必要があります。

3 - 私はMSDNで説明した脅威を除き、これに任意のマイナス面を見ることができない

<customBinding> 
    <binding name="bindingConfig"> 
     <reliableSession/> 
     <httpsTransport/> 
    </binding> 
    </customBinding> 

信頼性の高いメッセージングおよびHTTPSトランスポートでカスタムバインディングを使用し、それはあなたのアプリケーションに依存します。

4 - アプリケーションがIISでhotsedされている場合は使用している他のセッションプロバイダー 、あなたは

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 

を設定し、あなたの状態のため

HttpContext.Current.Session 

に依存性があります。

または独自のCookieを実装する。

PS:これらのWCF設定では、呼び出しではなくサービスのアクティベーションのみをテストしました。

編集:ユーザーリクエストごとに、 TransportWithMessageCredentialセキュリティモードを実装しています(私はVBにあまり慣れていません。NETので)私の構文を許し:

サービスコードスニペット:

<ServiceContract(SessionMode:=SessionMode.Required)> 
Public Interface IService1 

    <OperationContract()> _ 
    Sub SetSessionValue(ByVal value As Integer) 

    <OperationContract()> _ 
    Function GetSessionValue() As Nullable(Of Integer) 

End Interface 

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession, 
    ConcurrencyMode:=ConcurrencyMode.Single)> 
Public Class Service1 
    Implements IService1 

    Private _sessionValue As Nullable(Of Integer) 

    Public Sub SetSessionValue(ByVal value As Integer) Implements IService1.SetSessionValue 
     _sessionValue = value 
    End Sub 

    Public Function GetSessionValue() As Nullable(Of Integer) Implements IService1.GetSessionValue 
     Return _sessionValue 
    End Function 
End Class 

Public Class MyUserNamePasswordValidator 
    Inherits System.IdentityModel.Selectors.UserNamePasswordValidator 

    Public Overrides Sub Validate(userName As String, password As String) 
     ' Credential validation logic 
     Return ' Accept anything 
    End Sub 

End Class 

サービス構成スニペット:

<system.serviceModel> 
    <services> 
    <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior"> 
     <endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" bindingConfiguration="bindingConf"/> 
     <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/> 
    </service> 
    </services> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="bindingConf"> 
     <security mode="TransportWithMessageCredential"> 
      <message clientCredentialType="UserName"/> 
     </security> 
     </binding> 
    </wsHttpBinding> 
    </bindings> 
    <behaviors> 
    <serviceBehaviors> 
     <behavior name="WcfService1.Service1Behavior"> 
     <serviceMetadata httpsGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
     <serviceCredentials> 
      <userNameAuthentication 
      userNamePasswordValidationMode="Custom" 
      customUserNamePasswordValidatorType="WcfService1.MyUserNamePasswordValidator, WcfService1"/> 
     </serviceCredentials> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 

クライアントのテストコードスニペット:

Imports System.Threading.Tasks 

Module Module1 

    Sub Main() 
     Parallel.For(0, 10, Sub(i) Test(i)) 
     Console.ReadLine() 
    End Sub 

    Sub Test(ByVal i As Integer) 
     Dim client As ServiceReference1.Service1Client 
     client = New ServiceReference1.Service1Client() 
     client.ClientCredentials.UserName.UserName = "login" 
     client.ClientCredentials.UserName.Password = "password" 
     Console.WriteLine("Session N° {0} : Value set to {0}", i) 
     client.SetSessionValue(i) 
     Dim response As Nullable(Of Integer) 
     response = client.GetSessionValue() 
     Console.WriteLine("Session N° {0} : Value returned : {0}", response) 
     client.Close() 
    End Sub 

End Module 
+0

私はあなたのソリューションをテストする時間がありません、賞金は10分で終わりますが、この答えは最も詳細なので、私はそれを受け入れます。カスタムバインディングまたはTransportWithMessageCredentialモードを使用するのに適しています。私はそれらを試してみる。ありがとうございました。 – hgulyan

+0

TransportWithMessageCredentialはwsHttpBindingでは機能しません。これはNetHttpBindingでのみ機能します。 http://msdn.microsoft.com/en-us/library/ms730879.aspx – hgulyan

+0

を確認してください。これは、私がカスタムバインディングを使用する唯一の方法であることを意味します。 – hgulyan

1

デフォルトでは、WSHttpBindingはセキュリティセッションのみを許可します。これはWCFの概念であり、トランスポートにリンクされていません。セキュリティセッションは、httpsを介したセッションではなく、相互認証を伴うセッションです。これは、メッセージセキュリティを追加することによって実現されます。あなたのサービスに基づいて

、あなたはこの設定クライアント側で

<bindings> 
     <wsHttpBinding> 
     <binding name="wsHttpBindingConfig"> 
      <security mode="TransportWithMessageCredential"> 
      <!-- configure transport & message security here if needed--> 
      </security> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 

を適用する必要があり、ここで

[TestMethod] 
    public void TestSecuritySession() 
    { 
     //remove this is certificate is valid 
     ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, sslPolicyErrors) => { return true; }); 

     var binding = new WSHttpBinding(); 
     binding.Security = new WSHttpSecurity() { Mode = SecurityMode.TransportWithMessageCredential}; 
     ChannelFactory<ITestService> Factory = new ChannelFactory<ITestService>(binding, new EndpointAddress("https://localhost/TestService.svc")); 

     Factory.Open(); 
     var channel = Factory.CreateChannel(); 

     //call service here 

     (channel as IClientChannel).Close(); 

     Factory.Close(); 
    } 
+0

InstanceContextMode PerSessionを作成すると、私のセッションはあなたのケースで動作しますか? – hgulyan

+0

@hgulyanはい、もちろんです。 1つのサービスメソッドでセッション/インスタンス固有のデータを返すことで、この動作を簡単にテストできます。 – Cybermaxs

1

wsHttpBindingは、WCFセッションをサポートするためにreliableSessionを必要とする単純なユニットテストで、かつ信頼性の高いセッションはカスタムが必要ですsslをサポートするためのバインドだから、sslとwsHttpBindingを使ってWCFセッションを尋ねるのは、私が知る限り、問題のように思えます。

+1

あなたは正しいと思いますが、私はsslとセッションの両方が必要な場合はどうすればいいですか? – hgulyan

関連する問題