13

wsHttpBindings と SSL を有効にした WCF サービスを使用していますが、WCF セッションを有効にしたいと考えています。

SessionMode を必須に変更した後

SessionMode:=SessionMode.Required

 以下に説明するエラーが表示されます。 

コントラクトにはセッションが必要ですが、バインディング '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

考えられるすべての解決策を試しましたが、見つけることができましたが、何も役に立ちませんでした。

信頼できるセッションを有効にするためのアドバイスがいくつかありますが、 sslでは機能しません(カスタム バインディングがある場合のみ)。httpsの代わりにhttpを使用するようアドバイスする人もいますが、可能であれば、現在の構成でセッションを有効にしたいと考えています。 .

これを達成するためのアプローチはありますか?

どんな種類の助けも大歓迎です。

4

3 に答える 3

24

wsHttpBinding で「セッション」が必要な場合は、信頼できるメッセージングまたはセキュリティ セッションのいずれかを使用する必要があります。(ソース:トランスポートのみのセキュリティで wsHttpBidning を使用して WCF セッションを有効にする方法)。

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 はセッションを提供しないため、標準のバインディングで Https を介した RM を禁止しました。

ここでそれについての msdn 宣伝文句を見つけました: http://msdn2.microsoft.com/en-us/library/ms733136.aspx 宣伝文句は「唯一の例外は HTTPS を使用する場合です。SSL セッションは、信頼できるセッションにバインドされていません。セキュリティ コンテキスト (SSL セッション) を共有するセッションは互いに保護されないため、これは脅威となります。アプリケーションによっては、これが実際の脅威である場合とそうでない場合があります。」</p>

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

可能性を要約するには、次のいずれかを実行できます。

1 - wsHttpBinding を保持し、トランスポート セキュリティを削除して、信頼できるメッセージングを有効にします。

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

しかし、SSL レイヤーが失われ、セキュリティの一部が失われます。

2 - wsHttpBinding を維持し、トランスポート セキュリティを維持し、メッセージ認証を追加します。

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

SSL セキュリティ レイヤーを保持できますが、クライアントは (任意の形式の) 資格情報を提供する必要があります。サービス側で資格情報を検証しなくても、WCF は資格情報を指定していないメッセージを拒否するため、偽の資格情報を提供する必要があります。 .

3 - 信頼できるメッセージングと HTTPS トランスポートでカスタム バインディングを使用する

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

MSDN で説明されている脅威を除いて、これにはマイナス面は見られません。それはアプリケーションによって異なります。

4 - 他のセッション プロバイダーを使用する アプリケーションが IIS でホット化されている場合は、設定できます

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

に依存し、

HttpContext.Current.Session

あなたの州のために。

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

PS : これらすべての WCF 構成について、呼び出しではなく、サービスのアクティブ化のみをテストしたことに注意してください。

編集: ユーザーの要求に応じて、セッションを実装wsHttpBindingする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
于 2012-10-04T10:42:40.047 に答える
1

wsHttpBinding には、WCF セッションをサポートするための trustedSession が必要であり、信頼できるセッションには、ssl をサポートするためのカスタム バインディングが必要です。そのため、ssl を介して wsHttpBinding を使用して WCF セッションを要求することは、私が知る限り問題外のようです。

于 2012-10-04T09:55:48.360 に答える
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();
    }
于 2012-10-04T09:23:17.770 に答える