使用wsHttpBinding并且没有Windows安全性的WCF会话

时间:2011-01-22 09:26:01

标签: .net wcf wcf-security wcf-binding wcf-sessions

我需要创建一个托管在IIS中的WCF服务,在服务器的内存中使用http传输和保持状态。虽然我知道有状态服务并不是一个好主意,但最后的约束对于使服务与传统客户端一起工作是必要的。

我的第一个想法是asp.net的会话来存储值。我在我的服务中激活了asp.net兼容模式,这使我可以访问HttpContext,但是放在会话对象中的值没有被保存在内存中。我认为这是因为处理会话状态的http模块没有正确配置,但是当我在网上搜索得到答案时,WCF会话并认为使用它们可能更好。

但是,WCF会话看起来像是在文档下并在服务上放置了一组奇怪的先决条件,而且我找不到适合我需要的配置:必须在IIS中托管,必须使用http或https传输并且无法回复Windows身份验证,因为客户端和服务器不属于同一个域。我试图使用wsHttpBinding来实现这一点,我听说过WCF会话需要安全性或可靠消息,但是: - 使用标准绑定,当服务器不属于同一个域时,它失败并显示“SecurityNegotiationException调用者未通过服务进行身份验证”异常。这是相当合理的,因为它使用的是Windows安全性。

  • 如果我禁用安全性完成,则会失败并显示“合同需要会话,但绑定'WSHttpBinding'不支持它或未正确配置以支持它。”

  • 如果在保持安全性被禁用的同时启用可靠消息,我会收到异常“绑定验证失败,因为WSHttpBinding不支持基于传输安全性的可靠会话(HTTPS)。无法打开通道工厂或服务主机。使用消息安全性通过HTTP进行安全可靠的消息传递。“

  • 我已尝试启用传输级别安全性,但这似乎对生成的错误没有任何影响

是否有任何可能对我有用的配置?或者我应该回到使用asp.net会话的计划吗?

2 个答案:

答案 0 :(得分:25)

您可以以非常简单的方式在内存中保存WCF会话信息。为了消除我的指示中的任何可能的外部影响,我假设你开始一个全新的项目:

  1. 创建新的WCF服务库项目。此项目已包含预先配置了WSHttpBiding绑定的服务。
  2. 转到服务合同(IService1.cs)并将ServiceContract属性更改为以下内容:

    [ServiceContract(SessionMode = SessionMode.Required)]
    
  3. 转到服务实现(Service1.cs)并将以下ServiceBehavior属性添加到服务类(Service1):

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
    
  4. 将会话数据添加为服务类(Service1)的成员:

    public class Service1 : IService1
    {
        ...
    
        private string UserFullName { get; set; }
    
        ...
    }
    
  5. 使用成员显示会话特定数据(还记得将它们添加到服务合同中IService1):

    public class Service1 : IService1
    {
        ...
    
        public string Welcome(string fullName)
        {
            UserFullName = fullName ?? "Guest";
            return string.Format("Welcome back, {0}!", UserFullName);
        }
    
        public string Goodbye()
        {
            return string.Format("Come back soon, {0}!", UserFullName ?? "Guest");
        }
    
        ...
    }
    
  6. SessionMode.Required 可确保对您的客户进行会话跟踪 InstanceContextMode.PerSession 确保为每个会话创建服务类(Service1)的实例,以便您可以在其中保留会话数据,并且它将存储在内存中的多个调用中会话。
    ConcurrencyMode.Single 确保只有一个线程可以进入每个服务类实例(Service1),并且如果您只访问服务类(和外部线程安全位置)中的数据,则可以防止可能的并发问题。

    编辑:默认情况下,WSHttpBinding仅允许安全会话。但它也支持可靠的会话,允许在没有启用安全性的情况下建立会话。以下绑定配置会禁用安全性并启用可靠会话:

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

答案 1 :(得分:1)

IMO当你使用像WCF这样的HTTP抽象不佳的技术时会发生这种情况。 WCF Web服务理论上可以在没有HTTP的情况下托管(即通过NET TCP,MSMQ等),这使得很难使用HTTP的内置功能而无需进入配置地狱并开始“猜测正确配置”的游戏通过反复试验“你在哪里尝试所有可能的配置排列,直到你找到了正确的一个有效的方式!

最终,如果您无法使用WCF并且必须从头开始实施Web服务,则只需在客户端成功通过身份验证后设置cookie。然后,每个客户端请求只需获取该cookie引用的会话信息。

如果你不得不使用WCF,一个可能的解决方案就是自己动手进行会话管理(这是我在努力工作所需的努力时所做的事情)并拥有所有需要会话/身份验证的Web服务上的显式“会话”属性(通常是在身份验证上生成的guid)。因此,对于每个后续请求,您都可以使用guid来重新水化与该客户端关联的会话信息。

如果您对尝试不同的Web服务框架感兴趣,我会使用Open Source Web Services Framework来构建免费,干燥,可测试的Web服务,其中(无需任何配置)您创建的每个Web服务都是自动的可通过REST XML,JSON,JSV,SOAP 1.1,SOAP 1.2端点访问。实际上,它允许您通过HTTP GET URL访问相同的Web服务,以便REST-ful客户端和简单的调试以及SOAP端点(一些企业仍然强制要求的流行选择)。 Hello World教程应该为您提供一些有关其功能及其工作原理的概述。