【发布时间】:2011-10-26 16:11:41
【问题描述】:
我有一组使用带有 IIS 的 wsHttpBinding 设置的 WCF 服务,并且已经实现了自定义安全性(使用消息头)来确定发出请求的用户。我一直认为,基于几年的 netTcpBinding 经验(使用 Windows 服务来托管,而不是 IIS),WCF 端点收到的每个请求最终都会在一个新线程上结束。使用这个假设,我的自定义安全类(它实现 IDispatchMessageInspector)根据在消息头中找到“令牌”(一个 Guid)来设置线程标识,如下所示:
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
string token = string.Empty;
if (request.Headers.FindHeader("SecurityToken", Primitives.SerializationNamespace) > -1)
token = request.Headers.GetHeader<string>("SecurityToken", Primitives.SerializationNamespace);
if (!string.IsNullOrEmpty(token))
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(token, "AppName"), new string[] { "testrole" });
else
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("guest", "AppName"), new string[] { });
}
return null;
}
虽然在测试中,尽管我的内部变量(包含用户对象)被标记为 ThreadStatic,但新请求似乎保留了先前调用者的身份。
这是一个例子:
[ThreadStatic]
private static User _CurrentUser = null;
internal static User CurrentUser
{
get
{
//this holds the value of the previous caller's identity still, even though the
//thread's Identity.Name is now equal to the new caller's Guid
if (_CurrentUser == null)
_CurrentUser = UserData.GetByToken(Thread.CurrentPrincipal.Identity.Name);
return _CurrentUser;
}
}
我还尝试使用以下属性标记我所有的服务实现(直接在 .svc 文件后面),但这并没有改变任何东西:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
关于如何保证每个请求都在新线程上的任何想法?或者有没有更好的方法来存储/确定发出请求的用户是谁,而没有任何可能的重叠?
【问题讨论】:
-
你到底为什么要玩
ThreadStatic?你想完成什么?
标签: multithreading wcf iis