3

我已经实现了一个 Web API。

<authentication mode="None" />

我正在使用基本授权,并在我的 AuthorizeAttribute 中设置 Thread.CurrentPrincipal。

第一次启动/调试应用程序后,我提交一个请求,设置 Thread.CurrentPrincipal(IsAuthenticated = true)服务器端,IsAuthenticated 在我的控制器中返回 true,正如预期的那样。但是,此后的任何请求都会将 Thread.CurrentPrincipal 设置为正常,但是当执行到达我的控制器方法时,控制器的 User.Identity 属性已更改,并且 IsAuthenticated = false。

我无法弄清楚为什么 IsAuthenticated=true 仅在启动应用程序后第一次出现?!应该是每次,因为我正在手动设置 Thread.CurrentPrinciple,但是介于两者之间并击中我的控制器,它正在被替换!

更新

这与我添加的 MediaTypeFormatter 有关。当我删除格式化程序时,我没有得到问题。执行的格式化程序代码如下:

public override Task<object> ReadFromStreamAsync(Type type, System.IO.Stream webStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
    {
        return Task.Factory.StartNew(() =>
        {
            string temporaryFilePath = Path.Combine(TemporaryDirectory, Path.GetRandomFileName());

            using (FileStream fileStream = new FileStream(temporaryFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
            {
                webStream.CopyTo(fileStream);
            }

            return (object)new CustomFile(temporaryFilePath);
        });
    }
4

1 回答 1

2

答案在这里有一些详细的解释。

总之,设置 Thread.CurrentPrincipal 是不够的。我现在也设置了 HttpContext.Current.User,它正在工作。

在原始帖子中,调用了 MediaTypeFormatter 上的异步方法,创建了额外的线程,导致 CurrentPrinciple 被附加到其他线程,而不是最终执行控制器操作的线程。

至于为什么要设置在两个地方,可以在这里找到解释。它说:

如果您的应用程序执行任何自定义身份验证逻辑,则必须在两个位置设置主体:

Thread.CurrentPrincipal:此属性是在 .NET 中设置线程主体的标准方法。HttpContext.Current.User:此属性特定于 ASP.NET。

以下代码显示了如何设置主体:

private void SetPrincipal(IPrincipal principal)
{
    Thread.CurrentPrincipal = principal;
    if (HttpContext.Current != null)
    {
        HttpContext.Current.User = principal;
    }
}

对于虚拟主机,您必须在两个地方设置主体;否则安全上下文可能会变得不一致。但是,对于自托管,HttpContext.Current 为空。因此,为确保您的代码与主机无关,请在分配给 HttpContext.Current 之前检查 null,如图所示。

于 2013-06-13T21:27:34.917 回答