如何在 WCF 中啟用帶有 SSL wsHttpBinding 的會話
我有一個啟用了 wsHttpBindings 和 SSL 的 WCF 服務,但我想啟用 WCF 會話。
將 SessionMode 更改為 required 後
SessionMode:=SessionMode.Required我收到下面描述的錯誤。
契約需要 Session,但 Binding ‘WSHttpBinding’ 不支持它或未正確配置以支持它。
這是我的範例應用程序。
應用程序配置
<?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測試服務.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(如果只有您有自定義綁定),其他建議使用http而不是https,但如果可能的話,我想使用我目前的配置啟用 Sessions .
有什麼方法可以實現這一目標嗎?
非常感謝任何形式的幫助。
如果您想使用 wsHttpBinding 進行“會話”,則必須使用可靠消息傳遞或安全會話。(來源:如何使用 wsHttpBidning 和 Transport only Security 啟用 WCF 會話)。
WSHttpBinding 支持會話,但前提是啟用了安全性 (SecureConversation) 或可靠消息傳遞。如果您使用傳輸安全性,那麼它不使用 WS-SecureConversation 並且預設情況下 WS-ReliableMessaging 處於關閉狀態。因此 WSHttpBinding 用於會話的兩種協議不可用。您要麼需要使用消息安全性,要麼需要打開可靠會話。(來源:http ://social.msdn.microsoft.com/Forums/en-US/wcf/thread/57b3453e-e7e8-4875-ba23-3be4fff080ea/ )。
我們在標準綁定中不允許 RM over Https,因為保護 RM 會話的方法是使用安全會話,而 Https 不提供會話。
我在這裡找到了關於它的 msdn 簡介:http: //msdn2.microsoft.com/en-us/library/ms733136.aspx 簡介是“唯一的例外是使用 HTTPS 時。SSL 會話未綁定到可靠會話。這造成了威脅,因為共享安全上下文(SSL 會話)的會話彼此之間沒有受到保護;這可能是也可能不是真正的威脅,具體取決於應用程序。”
但是,如果您確定沒有威脅,您可以這樣做。通過自定義綁定有一個 RM over HTTPS 範例http://msdn2.microsoft.com/en-us/library/ms735116.aspx(來源: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