C# WCF web服务中的安全上下文令牌无效或已过期

C# WCF web服务中的安全上下文令牌无效或已过期,c#,wcf,iis,active-directory,wcf-security,C#,Wcf,Iis,Active Directory,Wcf Security,全部, 我使用服务帐户(VM,Windows2003SP2)在IIS下托管了一个WCFWeb服务(称为服务“B”)。该服务公开使用WSHttpBinding的端点,该端点具有默认值,但maxReceivedMessageSize、maxBufferPoolSize、maxBufferSize和一些已增加的超时除外 该web服务已使用VisualStudio负载测试框架对大约800名并发用户进行了负载测试,并成功通过了所有测试,没有引发异常。单元测试中的代理已根据配置创建 有一个sharepoin

全部,

我使用服务帐户(VM,Windows2003SP2)在IIS下托管了一个WCFWeb服务(称为服务“B”)。该服务公开使用WSHttpBinding的端点,该端点具有默认值,但maxReceivedMessageSize、maxBufferPoolSize、maxBufferSize和一些已增加的超时除外

该web服务已使用VisualStudio负载测试框架对大约800名并发用户进行了负载测试,并成功通过了所有测试,没有引发异常。单元测试中的代理已根据配置创建

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

当服务“A”所用时间少于10分钟时,呼叫服务“B”的呼叫成功。但当服务“A”需要更多时间(约20分钟)时,对服务“B”的调用会引发以下异常:

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

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

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

资料来源:安全

类别:登录/注销

活动编号:537

用户NT权限\系统

登录失败:

原因:登录期间发生错误

登录类型:3

登录进程:Kerberos

身份验证包:Kerberos

状态代码:0xC000006D

子状态代码:0xC0000133

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

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

有没有人经历过这种问题或有什么想法

问候,


--达米安

我相信这里发生的是你的频道超时了(正如你所怀疑的那样)

如果我理解正确的话,不是呼叫服务A超时,而是呼叫服务B,然后再呼叫您的操作

我猜您是在呼叫服务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应用程序的代理(称为服务A)将超时。 为了解决这个问题,您可能希望将服务模型从请求-响应更改为发布-订阅模型

使用长时间运行的服务,您将希望您的sharepoint应用程序订阅服务A,并让服务A在准备好时发布其结果,而不管需要多长时间

Juval Lowey的WCF服务编程(O'Reilly)有一个很好的解释,IDesign(Juval的公司)出版了,还有一个很好的例子的代码

希望这有帮助,
Assaf。

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


旋转一下,为客户端和服务器设置establishSecurityContext=“false”。

不要在using语句中调用服务操作。而是使用一种模式,例如

client = new ServiceClient("Ws<binding>")
try
{
    client.Operation(x,y);
    client.Close();
}
catch ()
{
    client.Abort();
}
client=newserviceclient(“Ws”)
尝试
{
客户操作(x,y);
client.Close();
}
捕获()
{
client.Abort();
}

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

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

我停止使用Station for service。如果需要处理它,请调用显式((IDispose)服务).dispose();最后,using语句的问题是,如果在调用过程中出现异常,using语句