简体   繁体   中英

WCF wsHttpBinding with IIS

I have a set of WCF services setup using wsHttpBinding with IIS and have implemented custom security (using message headers) to determine the user who is making the request. It has always been my understanding, based on a few years of netTcpBinding experience (using a Windows service to host, not IIS), that every request received by a WCF endpoint ends up on a new thread. Using this assumption, my custom security class (which implements IDispatchMessageInspector) sets the thread identity based on finding the "token" (a Guid) in the message header like so:

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;
 }

In testing this though, and despite my internal variable (which contains the user object) being marked ThreadStatic, new requests seem to retain the previous caller's identity.

Here's an example:

[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;
        }
    }

I also tried marking all of my service implementation's (directly behind the .svc file) with the following attribute but that didn't change anything:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

Any ideas on how I can guarantee every request is on a new thread? Or is there a better way to store/determine who the user making the request is without any possible overlap?

Using ThreadStatic variable in the environment where you don't have threading under your control is way to disaster. Both WCF (IIS and self-hosted) and ASP.NET internally use thread pool = each request is served by separate thread but these threads are reused for subsequent requests and there is not way to avoid it.

Use custom OperationContext extension to store your user instead of ThreadStatic variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM