.net WebApi:User.Identity.IsAuthenticated第一个请求为true,之后为false

.net WebApi:User.Identity.IsAuthenticated第一个请求为true,之后为false,.net,asp.net-web-api,basic-authentication,.net,Asp.net Web Api,Basic Authentication,我已经实现了一个Web API <authentication mode="None" /> 我正在使用基本授权,并在authorized属性中设置Thread.CurrentPrincipal 在启动/调试应用程序后的第一次,我提交了一个请求,设置了Thread.CurrentPrincipal(IsAuthenticated=true)服务器端,IsAuthenticated在我的控制器中按预期返回true。但是,在此之后的任何请求都会将Thread.CurrentPrin

我已经实现了一个Web API

<authentication mode="None" />

我正在使用基本授权,并在authorized属性中设置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);
        });
    }
public override Task ReadFromStreamAsync(类型类型、System.IO.Stream webStream、System.Net.Http.HttpContent内容、IFormatterLogger格式记录器)
{
返回Task.Factory.StartNew(()=>
{
字符串temporaryFilePath=Path.Combine(TemporaryDirectory,Path.GetRandomFileName());
使用(FileStream FileStream=newfilestream(临时文件路径,FileMode.CreateNew,FileAccess.Write,FileShare.Read))
{
CopyTo(fileStream);
}
返回(对象)新自定义文件(临时文件路径);
});
}

答案有详细解释

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

在最初的文章中,调用了MediaTypeFormatter上的async方法,创建了其他线程,导致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;
    }
}
对于web托管,必须在两个位置设置主体;否则 安全上下文可能变得不一致。对于自托管, 但是,HttpContext.Current为null。确保您的代码是正确的 因此,主机不可知,请在分配给之前检查null HttpContext.Current,如图所示