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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/912580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:39:51  来源:igfitidea点击:

Invalid or expired security context token in WCF web service

c#wcfiisactive-directorywcf-security

提问by

All,

全部,

I have a WCF web service (let's called service "B") hosted under IIS using a service account (VM, Windows 2003 SP2). The service exposes an endpoint that use WSHttpBinding with the default values except for maxReceivedMessageSize, maxBufferPoolSize, maxBufferSize and some of the time outs that have been increased.

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

The web service has been load tested using Visual Studio Load Test framework with around 800 concurrent users and successfully passed all tests with no exceptions being thrown. The proxy in the unit test has been created from configuration.

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

There is a sharepoint application that use the Office Sharepoint Server Search service to call web services "A" and "B". The application will get data from service "A" to create a request that will be sent to service "B". The response coming from service "B" is indexed for search. The proxy is created programmatically using the ChannelFactory.

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

When service "A" takes less than 10 minutes, the calls to service "B" are successfull. But when service "A" takes more time (~20 minutes) the calls to service "B" throw the following exception:

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

Exception Message: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail Inner Exception Message: The message could not be processed. This is most likely because the action 'namespace/OperationName' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.

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

The binding settings are the same, the time in both client server and web service server are synchronize with the Windows Time service, same time zone.

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

When i look at the server where web service "B" is hosted i can see the following security errors being logged:

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

Source: Security

来源:安全

Category: Logon/Logoff

类别:登录/注销

Event ID: 537

事件 ID:537

User NT AUTHORITY\SYSTEM

用户 NT AUTHORITY\SYSTEM

Logon Failure:

登录失败:

Reason: An error occurred during logon

原因:登录时发生错误

Logon Type: 3

登录类型:3

Logon Process: Kerberos

登录过程:Kerberos

Authentication Package: Kerberos

身份验证包:Kerberos

Status code: 0xC000006D

状态码:0xC000006D

Substatus code: 0xC0000133

子状态代码:0xC0000133

After reading some of the blogs online, the Status code means STATUS_LOGON_FAILURE and the substatus code means STATUS_TIME_DIFFERENCE_AT_DC. but i already checked both server and client clocks and they are syncronized.

看了网上的一些博客,状态码是STATUS_LOGON_FAILURE,子状态码是STATUS_TIME_DIFFERENCE_AT_DC。但我已经检查了服务器和客户端时钟并且它们是同步的。

I also noticed that the security token seems to be cached somewhere in the client server because they have another process that calls the web service "B" using the same service account and successfully gets data the first time is called. Then they start the proccess to update the office sharepoint server search service indexes and it fails. Then if they called the first proccess again it will fail too.

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

Has anyone experienced this type of problems or have any ideas?

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

Regards,

问候,

--Damian

--达米安

回答by Assaf Stone

What I believe is happening here is that your channel is timing out (as you suspect).

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

If I understand correctly, it is not the calls to service Athat are timing out, but rather to service B, beforeyou call your operation.

如果我理解正确,您调用操作之前,超时的不是对服务A的调用,而是对服务B 的调用。

I'm guessing that you are creating your channel beforeyou call service A, rather than just in time(i.e. before calling service B). You should create the channel (proxy, service client) just before you use it like:

我猜您是调用服务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;

I believe however, that once you get over thatproblem (service B timing out), you'll realize that the sharepoint app's proxy (that called service A) will timeout. To solve that, you may wish to change your service model from a request-response, to a publish-subscribe model.

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

With long-running services, you'll want your sharepoint app to subscribe to service A, and have service A publish its results when it is ready to do so - regardless of how long it takes.

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

Programming WCF Services (O'Reilly) by Juval Lowey, has a great explanation, and IDesign (Juval's company) published a great set of coding standards for WCF, as well as the code for a great Publish-Subscribe Framework.

由 Juval Lowey 编写的 Programming WCF Services (O'Reilly) 有一个很好的解释,IDesign(Juval 的公司)发布了一套很棒的 WCF 编码标准,以及一个很棒的Publish-Subscribe Framework的代码。

Hope this helps, Assaf.

希望这会有所帮助,阿萨夫。

回答by Alex

10 mins is the default receive timeout. If you have an idled proxy for more than 10mins, the security session of that proxy is aborted by the server. Enable logging and you will see this in the diagnostics log of the server. The error message you reported fits for this behavior. Search your system diagnostic file for "SessionIdleManager". If you find it, the above is your problem.

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

Give it a whirl and set the establishSecurityContext="false" for the client and the server.

试一试并为客户端和服务器设置建立SecurityContext="false"。

回答by MarkB

Don't call the service operation in a using statement. Instead use a pattern such as...

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

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

I don't understand why this works but I would guess that when the proxy goes out of scope in the using statement, Close isn't called. The service then waits until receiveTimeout (on the binding) has expired and then aborts the connection causing subsequent calls to fail.

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

回答by strongopinions

I actually triggered this error just now by doing something silly. I have a unit test that modifies the system date in order to test some time-based features. And I guess the apparent time difference between when I created the context and when I called my method (because of the changes to the system date), caused something to expire.

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