English 中文(简体)
ASP.Net WCF service s Thread.CurrentPrincipal is being thrown away by some interceptor in a Federated (WIF) environment
原标题:

I have a per-call WCF service that s being hosted in IIS (.svc). In the service s constructor, I set Thread.CurrentPrincipal = HttpContext.Current.User as per this article. In this case HttpContext.Current.User is of type Microsoft.IdentityModel.Claims.ClaimsPrincipal and has the claims that were sent back from my custom passive STS.

However, as soon as I step into my service operation and examine Thread.CurrentPrincipal, while this object is still of type Microsoft.IdentityModel.Claims.ClaimsIdentity, the object itself is no longer the same as HttpContext.Current.User (IsAuthenticated = false, AuthenticationType = "" and Name is null on Thread.CurrentPrincipal.Identity), whereas these values are all still filled in correctly on HttpContext.Current.User. This tells me that something is intercepting the call to the operation and incorrectly changing the current principal to some generic, empty, unauthenticated claims principal.

I checked the thread ID in the constructor as well as in the operation and it s the same in both places, and evaluating Thread.CurrentPrincipal in the immediate window after assigning from HttpContext.Current.User shows that the thread identity is being set correctly in the constructor, so something is definitely executing in between the constructor and the method, and that something is changing my Thread.CurrentPrincipal.

Does anybody have any idea what is doing this, and how I can go about preventing / fixing this behaviour?

最佳回答

When configuring a service for WIF federation, you call

FederatedServiceCredentials.ConfigureServiceHost(this);

Part of what this call does is to set up a custom ServiceAuthorizationManager of type IdentityModelServiceAuthorizationManager on the service host. This authorization manager appears to get called in between activation (construction) of the instance and execution of the operation, and it overwrites Thread.CurrentPrincipal with an instance of IClaimsPrincipal, but it doesn t seem to realize that it s running in ASP.NET Compatibility mode, so it doesn t pull the principal from HttpContext.Current.User.

I was able to bypass this behaviour by deriving from IdentityModelServiceAuthorizationManager and overriding the CheckAccess method as follows:

public class CustomAuthorizationManager : IdentityModelServiceAuthorizationManager
{
    public override bool CheckAccess(System.ServiceModel.OperationContext operationContext, ref System.ServiceModel.Channels.Message message)
    {
        var result = base.CheckAccess(operationContext, ref message);

        var properties = operationContext.ServiceSecurityContext.AuthorizationContext.Properties;
        properties["Principal"] = System.Web.HttpContext.Current.User;

        return result;
    }
}

This then gets applied to the service host as follows:

protected override void InitializeRuntime()
{
    FederatedServiceCredentials.ConfigureServiceHost(this);
    this.Authorization.ServiceAuthorizationManager = new CustomAuthorizationManager();
    base.InitializeRuntime();
}

And now when I enter my service operation, I have the correct IClaimsPrincipal on Thread.CurrentPrincipal, so declarative PrincipalPermission now works as expected.

问题回答

I just ran into a similar problem. I set my custom principal in the constructor of my WCF service. When I left the constructor, and entered the method I called, the thread.currentprincipal was overridden by an empty one. I solved this by adding the following behavior:

<serviceAuthorization principalPermissionMode="None"></serviceAuthorization>

This worked fine for me.

confguration settings for call FederatedServiceCredentials.ConfigureServiceHost(this);

is as below in system.serviceModel add following

<extensions>
      <behaviorExtensions>
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </behaviorExtensions>
    </extensions>

under inside add folowing line

<behavior name="serviceBehavior">
          <federatedServiceHostConfiguration name="MyService" />

My guess is that nothing is intercepting the call. Either the CurrentPrincipal is reset by the time you re examining it or you re in a different thread.

Check the CurrentPrincipal immediately after assigning to it and you should see the correct value.





相关问题
WCF DataMember Serializing questions

Ok, so I was part way through the long winded process of creating DTOs for sending my model over the wire and I don t feel like I m going down the right route. My issue is that most of the entities ...

Access WCF service on same server

I have a .NET website with a WCF service. How do I access the current operations context of my service? One possible work around is to just make a call to the service within the app...but that seems ...

WCF binding error

So I got into work early today and got the latest from source control. When I try to launch our ASP.NET application, I get this exception: "The binding at system.serviceModel/bindings/wsHttpBinding ...

The service operation requires a transaction to be flowed

I am facing strange issue with our WCF service. The same code was working fine until recently we added more OperationContracts(Web Methods). We have common 3 tier architecture. DAL (WCF) BLL Web ...

热门标签