2012-09-25 16 views
13

Tôi có một Dịch vụ WCF với wsHttpBindings và SSL được kích hoạt, nhưng tôi muốn kích hoạt các phiên WCF.Làm thế nào để kích hoạt Phiên với SSL wsHttpBinding trong WCF

Sau khi thay đổi SessionMode thành bắt buộc

SessionMode:=SessionMode.Required 

Tôi nhận được lỗi được mô tả dưới đây.

Hợp đồng yêu cầu Phiên, nhưng Ràng buộc 'WSHttpBinding' không hỗ trợ hoặc không được định cấu hình đúng để hỗ trợ.

Đây là ứng dụng mẫu của tôi.

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 

Tôi đã thử tất cả po giải pháp ssible, tôi có thể tìm thấy, nhưng không có gì giúp đỡ.

Một số lời khuyên để giúp phiên đáng tin cậy, nhưng nó không làm việc với ssl (nếu chỉ có bạn có tùy chỉnh của bạn ràng buộc), lời khuyên người khác sử dụng http thay vì https, nhưng tôi muốn muốn bật Phiên có cấu hình hiện tại của tôi, nếu có thể.

Có cách tiếp cận nào để đạt được điều này không?

Mọi loại trợ giúp đều được đánh giá cao.

+0

Lý do bật trạng thái phiên trên dịch vụ wcf là gì? Đây có thể là một nút cổ chai nếu bạn đang tìm kiếm hiệu suất cao. Dịch vụ wcf phiên trạng thái nên tránh. –

+0

Tôi muốn có biến _user cho mỗi phiên. Tôi nhận được một phiên bản dịch vụ mới cho mọi cuộc gọi. Giá trị của _user luôn là Không có gì. – hgulyan

+0

Tôi nên sử dụng giải pháp nào cho tình huống của mình, nếu tôi cần lưu trữ dữ liệu cho mọi khách hàng? – hgulyan

Trả lời

18

Nếu bạn muốn "phiên" với wsHttpBinding, bạn phải sử dụng tin nhắn đáng tin cậy hoặc các phiên bảo mật. (nguồn: how to enable WCF Session with wsHttpBidning with Transport only Security).

WSHttpBinding hỗ trợ phiên nhưng chỉ khi bảo mật (SecureConversation) hoặc tin nhắn đáng tin cậy được bật. Nếu bạn đang sử dụng bảo mật giao thông thì không sử dụng WS-SecureConversation và WS-ReliableMessaging được tắt theo mặc định. Do đó, hai giao thức WSHttpBinding sử dụng cho phiên không có sẵn. Bạn cần phải sử dụng bảo mật thư hoặc bật phiên đáng tin cậy. (nguồn: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/57b3453e-e7e8-4875-ba23-3be4fff080ea/).

Chúng tôi đã không cho phép RM trên Https trong các ràng buộc chuẩn vì cách để bảo đảm phiên RM là sử dụng phiên bảo mật và Https không cung cấp phiên.

Tôi đã tìm thấy msdn blurb về nó tại đây: http://msdn2.microsoft.com/en-us/library/ms733136.aspx Sự xáo trộn là “Ngoại lệ duy nhất là khi sử dụng HTTPS. Phiên SSL không bị ràng buộc vào phiên đáng tin cậy. Điều này áp đặt một mối đe dọa bởi vì các phiên chia sẻ một bối cảnh bảo mật (phiên SSL) không được bảo vệ lẫn nhau; điều này có thể hoặc có thể không phải là mối đe dọa thực sự tùy thuộc vào đơn đăng ký. ”

Tuy nhiên, bạn có thể làm điều đó nếu bạn xác định không có mối đe dọa nào. Có mẫu RM qua HTTPS qua ràng buộc tùy chỉnh http://msdn2.microsoft.com/en-us/library/ms735116.aspx (nguồn: http://social.msdn.microsoft.com/forums/en-US/wcf/thread/fb4e5e31-e9b0-4c24-856d-1c464bd0039c/).

Tóm lại khả năng của bạn, bạn có thể:

1 - Giữ wsHttpBinding, loại bỏ an ninh vận tải và cho phép gửi tin nhắn đáng tin cậy

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

Nhưng bạn mất lớp SSL và sau đó một phần của bảo mật của bạn .

2 - Giữ wsHttpBinding, giữ an ninh vận tải và thêm xác thực thông điệp

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

Bạn có thể giữ lớp bảo mật SSL của bạn, nhưng khách hàng của bạn sẽ phải cung cấp thông tin (của dưới mọi hình thức) và thậm chí nếu bạn không xác nhận chúng ở phía dịch vụ, những người giả mạo vẫn phải được cung cấp như WCF sẽ từ chối bất kỳ tin nhắn không chỉ định thông tin đăng nhập.

3 - Sử dụng một tùy chỉnh ràng buộc với thông điệp đáng tin cậy và vận chuyển HTTPS

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

Tôi không thể nhìn thấy bất cứ nhược điểm này, ngoại trừ các mối đe dọa được giải thích trong MSDN, và nó phụ thuộc vào ứng dụng của bạn.

4 - Sử dụng các nhà cung cấp phiên khác Nếu ứng dụng của bạn được hotsed trong IIS, bạn có thể thiết

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> 

và phụ thuộc vào

HttpContext.Current.Session 

cho tiểu bang.

Hoặc triển khai cookie của riêng bạn.

PS: Lưu ý rằng đối với tất cả cấu hình WCF đó, tôi chỉ kiểm tra kích hoạt dịch vụ chứ không phải cuộc gọi.

CHỈNH SỬA: Theo yêu cầu của người dùng, wsHttpBinding với TransportWithMessageCredential các phiên thực hiện chế độ bảo mật (Tôi không quá quen thuộc với VB.NET nên tha thứ cú pháp của tôi):

Service đoạn mã:

<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 

dịch vụ đoạn Cấu hình:

<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> 

Khách hàng đoạn mã kiểm tra:

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

Tôi không có thời gian để kiểm tra các giải pháp của bạn, tiền thưởng kết thúc sau 10 phút, nhưng câu trả lời này là chi tiết nhất, vì vậy tôi sẽ chấp nhận nó. Nó phù hợp với tôi để sử dụng tùy chỉnh ràng buộc hoặc TransportWithMessageCredential chế độ. Tôi sẽ thử cả hai. Cảm ơn bạn. – hgulyan

+0

TransportWithMessageCredential sẽ không hoạt động với wsHttpBinding. Nó chỉ hoạt động với NetHttpBinding. Kiểm tra http://msdn.microsoft.com/en-us/library/ms730879.aspx – hgulyan

+0

Nó có nghĩa là cách duy nhất có thể cho tôi là sử dụng một ràng buộc tùy chỉnh. – hgulyan

1

Theo mặc định, WSHttpBinding chỉ cho phép các phiên bảo mật. Nó là một khái niệm về WCF và không liên quan đến Giao thông vận tải. Phiên bảo mật không phải là phiên trên https, mà là phiên có xác thực lẫn nhau. Điều này đạt được bằng cách thêm bảo mật tin nhắn.

Dựa trên dịch vụ của bạn, bạn nên áp dụng cấu hình này

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

On clientside, đây là một thử nghiệm đơn vị đơn giản

[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

Phiên làm việc của tôi có hoạt động trong trường hợp của bạn không, nếu tôi tạo InstanceContextMode PerSession? – hgulyan

+0

@hgulyan Có tất nhiên. Bạn có thể dễ dàng kiểm tra hành vi này từ phía bạn bằng cách trả về dữ liệu cụ thể phiên/thể hiện trong một phương thức dịch vụ. – Cybermaxs

1

wsHttpBinding đòi hỏi reliableSession để hỗ trợ phiên WCF, và các buổi đáng tin cậy yêu cầu tùy chỉnh ràng buộc để hỗ trợ ssl. Vì vậy, yêu cầu cho các phiên WCF trên ssl và với wsHttpBinding có vẻ như trong số các câu hỏi như xa như tôi có thể nói.

+1

Tôi cho rằng, bạn nói đúng, nhưng tôi nên làm gì nếu tôi cần cả phiên làm việc và ssl? – hgulyan