在异步WCF最终方法不对Thread.CurrentPrincipal中 [英] Wrong Thread.CurrentPrincipal in async WCF end-method

查看:370
本文介绍了在异步WCF最终方法不对Thread.CurrentPrincipal中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有其中有一个WCF服务的 Thread.CurrentPrincipal中中设置的 ServiceConfiguration.ClaimsAuthorizationManager

I have a WCF service which has its Thread.CurrentPrincipal set in the ServiceConfiguration.ClaimsAuthorizationManager.

当我以异步方式实现服务是这样的:

When I implement the service asynchronously like this:

    public IAsyncResult BeginMethod1(AsyncCallback callback, object state)
    {
        // Audit log call (uses Thread.CurrentPrincipal)

        var task = Task<int>.Factory.StartNew(this.WorkerFunction, state);

        return task.ContinueWith(res => callback(task));
    }

    public string EndMethod1(IAsyncResult ar)
    {
        // Audit log result (uses Thread.CurrentPrincipal)

        return ar.AsyncState as string;
    }

    private int WorkerFunction(object state)
    {
        // perform work
    }

我发现Thread.CurrentPrincipal中被设置为正确的ClaimsPrincipal在开始-方法和也在WorkerFunction,但在最终的方法将其设置为一的GenericPrincipal

I find that the Thread.CurrentPrincipal is set to the correct ClaimsPrincipal in the Begin-method and also in the WorkerFunction, but in the End-method it's set to a GenericPrincipal.

我知道我可以启用ASP.NET兼容的服务,并使用 HttpContext.Current.User 这在所有的方法正确的主体,但我宁愿不做到这一点。

I know I can enable ASP.NET compatibility for the service and use HttpContext.Current.User which has the correct principal in all methods, but I'd rather not do this.

有没有办法来强制向Thread.CurrentPrincipal中正确ClaimsPrincipal没有打开ASP.NET兼容?

Is there a way to force the Thread.CurrentPrincipal to the correct ClaimsPrincipal without turning on ASP.NET compatibility?

推荐答案

WCF扩展点的总结,你会​​看到一个是前pressly设计来解决你的问题。它被称为<一href=\"http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.icallcontextinitializer%28v=vs.110%29.aspx\"相对=nofollow> CallContextInitializer 。看看这个<一个href=\"http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/14/wcf-extensibility-initializers-instance-context-channel-call-context.aspx\"相对=nofollow>文章这给CallContextInitializer样品code 。

Starting with a summary of WCF extension points, you'll see the one that is expressly designed to solve your problem. It is called a CallContextInitializer. Take a look at this article which gives CallContextInitializer sample code.

如果您进行ICallContextInitializer扩展,您将获得控制权都的BeginXXX线程上下文的的的EndXXX线程上下文。你是说,ClaimsAuthorizationManager已正确建立在你的BeginXXX(...)方法的用户主体。在这种情况下,你再为自己定制ICallContextInitializer它或者受让人或记录CurrentPrincipal,取决于它是否被处理您的BeginXXX()或EndXXX()。是这样的:

If you make an ICallContextInitializer extension, you will be given control over both the BeginXXX thread context AND the EndXXX thread context. You are saying that the ClaimsAuthorizationManager has correctly established the user principal in your BeginXXX(...) method. In that case, you then make for yourself a custom ICallContextInitializer which either assigns or records the CurrentPrincipal, depending on whether it is handling your BeginXXX() or your EndXXX(). Something like:

public object BeforeInvoke(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.IClientChannel channel, System.ServiceModel.Channels.Message request){
    object principal = null;
    if (request.Properties.TryGetValue("userPrincipal", out principal))
    {
        //If we got here, it means we're about to call the EndXXX(...) method.
        Thread.CurrentPrincipal = (IPrincipal)principal;
    }
    else
    {
        //If we got here, it means we're about to call the BeginXXX(...) method.
        request.Properties["userPrincipal"] = Thread.CurrentPrincipal;            
    }
    ...
 }

要进一步明确,考虑两种情况。假设你实现既是ICallContextInitializer和IParameterInspector。假设这些挂钩有望与同步WCF服务,并与一个异步WCF服务(这是你的特殊情况)来执行。

To clarify further, consider two cases. Suppose you implemented both an ICallContextInitializer and an IParameterInspector. Suppose that these hooks are expected to execute with a synchronous WCF service and with an async WCF service (which is your special case).

下面是事件的顺序和正在发生的事情的解释是:

Below are the sequence of events and the explanation of what is happening:

ICallContextInitializer.BeforeInvoke();
IParemeterInspector.BeforeCall();
//...service executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();

没什么希奇在上面code。但是,现在下面再看一下异步服务操作发生...

Nothing surprising in the above code. But now look below at what happens with asynchronous service operations...

ICallContextInitializer.BeforeInvoke();  //TryGetValue() fails, so this records the UserPrincipal.
IParameterInspector.BeforeCall();
//...Your BeginXXX() routine now executes...
ICallContextInitializer.AfterInvoke();

//...Now your Task async code executes (or finishes executing)...

ICallContextInitializercut.BeforeInvoke();  //TryGetValue succeeds, so this assigns the UserPrincipal.
//...Your EndXXX() routine now executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();

正如你所看到的,CallContextInitializer确保您有机会初始化值,如只是EndXXX()程序运行之前您CurrentPrincipal。因此,它无关紧要的EndXXX()函数肯定是在不同的线程执行比没有的BeginXXX()例程。是的,这是存储之间的用户主体的 System.ServiceModel.Channels.Message 对象开始/结束的方法,是preserved和WCF正确传输,即使线程改变。

As you can see, the CallContextInitializer ensures you have opportunity to initialize values such as your CurrentPrincipal just before the EndXXX() routine runs. It therefore doesn't matter that the EndXXX() routine assuredly is executing on a different thread than did the BeginXXX() routine. And yes, the System.ServiceModel.Channels.Message object which is storing your user principal between Begin/End methods, is preserved and properly transmitted by WCF even though the thread changed.

总体而言,这种方法可以让你的EndXXX(IAsyncResult的),用正确的IPrincipal来执行,而不需要在EndXXX()函数来明确重新建立CurrentPrincipal。而与任何WCF行为,可以这是否适用于个人业务,所有业务合同的所有操作,或在端点决定。

Overall, this approach allows your EndXXX(IAsyncresult) to execute with the correct IPrincipal, without having to explicitly re-establish the CurrentPrincipal in the EndXXX() routine. And as with any WCF behavior, you can decide if this applies to individual operations, all operations on a contract, or all operations on an endpoint.

这篇关于在异步WCF最终方法不对Thread.CurrentPrincipal中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆