WCF Web服务中的安全上下文令牌无效或过期

时间:2009-05-26 20:29:12

标签: c# wcf iis active-directory wcf-security

所有

我使用服务帐户(VM,Windows 2003 SP2)在IIS下托管了WCF Web服务(我们称之为服务“B”)。该服务公开了一个使用WSHttpBinding的端点,其默认值除了maxReceivedMessageSize,maxBufferPoolSize,maxBufferSize和一些已经增加的超时外。

使用Visual Studio Load Test框架对Web服务进行了负载测试,该框架包含大约800个并发用户,并成功通过了所有测试,没有抛出任何异常。单元测试中的代理已从配置创建。

有一个sharepoint应用程序使用Office Sharepoint Server Search服务来调用Web服务“A”和“B”。应用程序将从服务“A”获取数据以创建将发送到服务“B”的请求。来自服务“B”的响应被索引用于搜索。代理是使用ChannelFactory以编程方式创建的。

当服务“A”花费不到10分钟时,对服务“B”的调用成功。但是当服务“A”花费更多时间(约20分钟)时,对服务“B”的调用会抛出以下异常:

异常消息:从另一方收到了不安全或不正确安全的故障。请参阅内部FaultException以获取故障代码和详细信息 内部异常消息:无法处理消息。这很可能是因为操作'namespace / OperationName'不正确,或者因为消息包含无效或过期的安全上下文令牌,或者因为绑定之间存在不匹配。如果服务因不活动而中止通道,则安全上下文令牌将无效。要防止服务中止空闲会话,请过早增加服务端点绑定的接收超时。

绑定设置相同,客户端服务器和Web服务服务器中的时间与Windows时间服务同一时区同步。

当我查看托管Web服务“B”的服务器时,我可以看到记录了以下安全错误:

来源:安全

类别:登录/注销

事件ID:537

用户NT AUTHORITY \ SYSTEM

登录失败:

原因:登录期间发生错误

登录类型:3

登录过程:Kerberos

身份验证包:Kerberos

状态代码:0xC000006D

Substatus代码:0xC0000133

在线阅读了一些博客后,状态代码表示STATUS_LOGON_FAILURE,子状态代码表示STATUS_TIME_DIFFERENCE_AT_DC。但我已经检查了服务器和客户端时钟,它们是同步的。

我还注意到安全令牌似乎在客户端服务器的某处缓存,因为它们有另一个使用相同服务帐户调用Web服务“B”的进程,并在第一次调用时成功获取数据。然后他们启动进程来更新office sharepoint服务器搜索服务索引,但它失败了。然后,如果他们再次调用第一个进程,它也会失败。

有没有人遇到过这类问题或有任何想法?

此致

- 达米安

4 个答案:

答案 0 :(得分:5)

10分钟是默认的接收超时。如果您的闲置代理超过10分钟,则该代理的安全会话将被服务器中止。启用日志记录,您将在服务器的诊断日志中看到此信息。您报告的错误消息适合此行为。 在系统诊断文件中搜索“SessionIdleManager”。如果你找到它,上面就是你的问题。

给它一个旋转并为客户端和服务器设置establishSecurityContext =“false”。

答案 1 :(得分:3)

不要在using语句中调用服务操作。而是使用诸如......之类的模式。

client = new ServiceClient("Ws<binding>")
try
{
    client.Operation(x,y);
    client.Close();
}
catch ()
{
    client.Abort();
}

我不明白为什么会这样,但我猜想当代理超出using语句的范围时,不会调用Close。然后服务等待,直到receiveTimeout(在绑定上)已过期,然后中止连接,导致后续调用失败。

答案 2 :(得分:1)

我认为这里发生的是你的频道超时(正如你所怀疑的那样)。

如果我理解正确,那么服务 A 的提示是超时的,而不是在之前服务 B 打电话给你。

我猜你在之前创建了你的频道,而不是及时(即在致电服务之前)的)。您应该在使用之前创建频道(代理,服务客户端),如:

AResponse aResp = null;
BResponse bResp = null;
using (ServiceAProxy proxyA = new ServiceAProxy())
{
   aResp = proxyA.DoServiceAWork();
   using (ServiceBProxy proxyB = new ServiceBProxy())
   {
      bResp = proxyB.DoOtherork(aResp);
   }
}
return bResp;

但是我相信,一旦你克服 问题(服务B超时),你就会意识到sharepoint app的代理(称为服务 A )会超时。 要解决此问题,您可能希望将服务模型从请求 - 响应更改为发布 - 订阅模型。

对于长期运行的服务,您需要您的sharepoint应用程序订阅服务A,并让服务A在准备好时发布其结果 - 无论需要多长时间。

由Juval Lowey编写WCF服务(O'Reilly),有一个很好的解释,IDesign(Juval的公司)发布了a great set of coding standards for WCF,以及一个伟大的Publish-Subscribe Framework的代码。

希望这有帮助, 阿萨弗。

答案 3 :(得分:0)

我实际上是通过做一些愚蠢的事情来触发这个错误。我有一个单元测试,修改系统日期,以测试一些基于时间的功能。我猜我创建上下文和调用我的方法之间(由于系统日期的更改)之间的明显时间差异导致某些内容过期。