【问题标题】:Set Thread.CurrentPrincipal Asynchronously?异步设置 Thread.CurrentPrincipal?
【发布时间】:2013-05-09 06:52:37
【问题描述】:

使用 ASP.NET WebAPI,在身份验证期间设置Thread.CurrentPrincipal,以便控制器以后可以使用ApiController.User 属性。

如果该身份验证步骤变为异步(咨询另一个系统),CurrentPrincipal 的任何突变都会丢失(当调用者的 await 恢复同步上下文时)。

这是一个非常简化的示例(在实际代码中,身份验证发生在操作过滤器中):

using System.Diagnostics;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;

public class ExampleAsyncController : System.Web.Http.ApiController
{
    public async Task GetAsync()
    {
        await AuthenticateAsync();

        // The await above saved/restored the current synchronization
        // context, thus undoing the assignment in AuthenticateAsync(). 
        Debug.Assert(User is GenericPrincipal);
    }

    private static async Task AuthenticateAsync()
    {
        // Save the current HttpContext because it's null after await.
        var currentHttpContext = System.Web.HttpContext.Current;

        // Asynchronously determine identity.
        await Task.Delay(1000);
        var identity = new GenericIdentity("<name>");

        var roles = new string[] { };
        Thread.CurrentPrincipal = new GenericPrincipal(identity, roles);
        currentHttpContext.User = Thread.CurrentPrincipal;
    }
}

如何在异步函数中设置 Thread.CurrentPrincipal 以使调用者的 await 在恢复同步上下文时不会丢弃该突变?

【问题讨论】:

  • 我不确定您的问题,但理想情况下,最好在调用控制器之前对其进行身份验证。在我的 WebAPI 项目中,我喜欢设置一个 DelegatingHandler,它会在到达控制器之前进行身份验证。
  • @Matthew,我同意,这就是真实代码的工作方式,动作过滤器在调用控制器方法之前处理身份验证。我排除了操作过滤器以简化我的示例,但在任何一种情况下问题都是相同的。
  • 从这个 stackoverflow 答案看来,如果您设置 CurrentPrincipal,它将持续到调用线程:stackoverflow.com/a/12460170/507793,否则我不确定如何解决您的问题。

标签: c# asp.net-web-api async-await


【解决方案1】:

您还必须设置HttpContext.Current.User。请参阅this answerthis blog post 了解更多信息。

更新:还要确保您在 .NET 4.5 上运行并将 UserTaskFriendlySynchronizationContext 设置为 true

【讨论】:

  • 感谢您帮助斯蒂芬。我添加了HttpContext.Current.User 的设置(并更新了我的问题中的代码),但这没有帮助。问题没有改变。
  • 这绝对对我有用。我在 ValuesController 中使用上面的代码创建了一个新的 WebAPI 项目,它工作得很好。后续问题:您是否在 .NET 4.5 上运行,您是否将 UseTaskFriendlySynchronizationContext 设置为 true?
  • UseTaskFriendlySynchronizationContext 设置为 true 解决了问题!感谢您抽出宝贵时间进行调查!
  • 不客气!我编辑了答案以使其更完整。奇怪的是,在我的机器上,无论UTFSC 设置为true 还是false,它都可以工作。我不确定UTFSC 会在哪些条件下有所作为,但我很高兴它有所帮助!
  • 斯蒂芬,经过进一步调查,看来我的示例仅适用于存在await Task.Delay(1000)。我专门询问了a new question。如果您有时间,我将不胜感激您的任何意见。
猜你喜欢
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 2015-09-29
  • 1970-01-01
  • 2014-01-27
  • 2017-02-12
  • 1970-01-01
  • 2014-02-25
相关资源
最近更新 更多