服务代码片段:公共接口 IService1<OperationContract()>_Sub SetSessionValue(ByVal value As Integer)<OperationContract()>_函数 GetSessionValue() As Nullable(Of Integer)终端接口<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession,ConcurrencyMode:=ConcurrencyMode.Single)>公开课服务1实现 IService1Private _sessionValue 为 Nullable(Of Integer)Public Sub SetSessionValue(ByVal value As Integer) 实现 IService1.SetSessionValue_sessionValue = 值结束子公共函数 GetSessionValue() As Nullable(Of Integer) 实现 IService1.GetSessionValue返回 _sessionValue结束函数结束班公共类 MyUserNamePasswordValidator继承 System.IdentityModel.Selectors.UserNamePasswordValidatorPublic Overrides Sub Validate(userName As String, password As String)' 凭证验证逻辑Return '接受任何东西结束子结束班服务配置片段:<服务><服务名称="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior"><endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" bindingConfiguration="bindingConf"/><endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/></服务></服务><绑定><wsHttpBinding><binding name="bindingConf"><安全模式="TransportWithMessageCredential"><message clientCredentialType="用户名"/></安全></binding></wsHttpBinding></绑定><行为><服务行为><行为名称="WcfService1.Service1Behavior"><serviceMetadata httpsGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="false"/><serviceCredentials><用户名认证userNamePasswordValidationMode="自定义"customUserNamePasswordValidatorType="WcfService1.MyUserNamePasswordValidator, WcfService1"/></serviceCredentials></行为></serviceBehaviors></行为></system.serviceModel>客户端测试代码片段:导入 System.Threading.Tasks模块模块1子主()Parallel.For(0, 10, Sub(i) Test(i))Console.ReadLine()结束子子测试(ByVal i As Integer)Dim client As ServiceReference1.Service1Client客户端 = 新的 ServiceReference1.Service1Client()client.ClientCredentials.UserName.UserName = "登录"client.ClientCredentials.UserName.Password = "密码"Console.WriteLine("Session N° {0} : 值设置为 {0}", i)client.SetSessionValue(i)Dim 响应为 Nullable(Of Integer)响应 = client.GetSessionValue()Console.WriteLine("Session N° {0} : 返回值:{0}", response)客户端.关闭()结束子终端模块I have a WCF Service with wsHttpBindings and SSL enabled, but I'd like to enable WCF sessions.After changing SessionMode to requiredSessionMode:=SessionMode.Required I'm getting error described below. Here's my sample application.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 InterfaceTestService.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 ClassI tried all possible solutions, I could find, but nothing helped.Some advice to enable reliable sessions, but it doesn't work with ssl (if only you have your custom binding), others advice to use http instead of https, but I'd like to enable Sessions with my current configurations, if it's possible.Is there any approach to achieve this?Any kind of help is much appreciated. 解决方案 If you want "sessions" with wsHttpBinding, you have to use either reliable messaging, or the security sessions. (source : how to enable WCF Session with wsHttpBidning with Transport only Security).WSHttpBinding supports session but only if either security (SecureConversation) or reliable messaging are enabled.If you are using transport security then it is not using WS-SecureConversation and WS-ReliableMessaging is turned off by default. Therefore the two protocols that WSHttpBinding uses for session are not available. You either need to use message security or turn on reliable session. (source : http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/57b3453e-e7e8-4875-ba23-3be4fff080ea/).We’ve disallowed RM over Https in the standard bindings because the way to secure an RM session is to use a security session and Https does not provide session.I found the msdn blurb about it here: http://msdn2.microsoft.com/en-us/library/ms733136.aspxThe blurb is "The only exception is when using HTTPS. The SSL session is not bound to the reliable session. This imposes a threat because sessions sharing a security context (the SSL session) are not protected from each other; this might or might not be a real threat depending on the application."However you can do it if you determine there is no threat. There is an RM over HTTPS sample via custom binding http://msdn2.microsoft.com/en-us/library/ms735116.aspx (source : http://social.msdn.microsoft.com/forums/en-US/wcf/thread/fb4e5e31-e9b0-4c24-856d-1c464bd0039c/).To sum up your possibilities you can either :1 - Keep wsHttpBinding, remove transport security and enable reliable messaging <wsHttpBinding> <binding name="bindingConfig"> <reliableSession enabled="true" /> <security mode="None"/> </binding> </wsHttpBinding>But you loose the SSL layer and then part of your security.2 - Keep wsHttpBinding, keep transport security and add message authentication <wsHttpBinding> <binding name="bindingConfig"> <security mode="TransportWithMessageCredential"> <message clientCredentialType="UserName"/> </security> </binding> </wsHttpBinding>You get to keep your SSL security layer but your client will have to provide credentials (of any form) and even if you don't validate them at the service side, fake ones must still be provided as WCF will reject any message not specifying credentials.3 - Use a custom binding with reliable messaging and HTTPS transport <customBinding> <binding name="bindingConfig"> <reliableSession/> <httpsTransport/> </binding> </customBinding>I can't see any downside to this except the threat explained in MSDN, and it depends on your application.4 - Use other session providersIf your application is hotsed in IIS, you could set <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>and depend on the HttpContext.Current.Sessionfor your state.Or implementing your own cookies.PS : Note that for all those WCF configuration, I only tested service activation, not calls.EDIT : As per user request, wsHttpBinding with TransportWithMessageCredential security mode implementing sessions (I'm not too familiar with VB.NET so pardon my syntax) :Service code snippet :<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 FunctionEnd ClassPublic Class MyUserNamePasswordValidator Inherits System.IdentityModel.Selectors.UserNamePasswordValidator Public Overrides Sub Validate(userName As String, password As String) ' Credential validation logic Return ' Accept anything End SubEnd Classservice Configuration snippet : <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>Client test code snippet : Imports System.Threading.TasksModule 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 SubEnd Module 这篇关于如何在 WCF 中使用 SSL wsHttpBinding 启用会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-31 07:41