C# 为什么在使用Simple Injector创建实例时Thread.CurrentPrincipal.Identity.IsAuthenticated为false

C# 为什么在使用Simple Injector创建实例时Thread.CurrentPrincipal.Identity.IsAuthenticated为false,c#,asp.net-web-api2,simple-injector,claims,iprincipal,C#,Asp.net Web Api2,Simple Injector,Claims,Iprincipal,基本上,我试图获取当前正在访问Web Api的经过身份验证的用户(通过承载令牌)的声明集;通过将当前主体注入助手类,然后将其注入到注入ApicController的类中 但是,返回的主体永远不是我想要的主体,因为它没有经过身份验证,也不包含任何声明。如果在创建ApiController后,我单步进入ApiController的构造函数,则本地ApiController.User principal值设置正确 下面是我创建并链接到下面的示例解决方案中的一些代码 货柜登记: namespace Pr

基本上,我试图获取当前正在访问Web Api的经过身份验证的用户(通过承载令牌)的声明集;通过将当前主体注入助手类,然后将其注入到注入ApicController的类中

但是,返回的主体永远不是我想要的主体,因为它没有经过身份验证,也不包含任何声明。如果在创建ApiController后,我单步进入ApiController的构造函数,则本地ApiController.User principal值设置正确

下面是我创建并链接到下面的示例解决方案中的一些代码

货柜登记:

namespace PrincipalInjector
{
    using System.Security.Principal;
    using System.Threading;
    using System.Web;
    using System.Web.Http;

    using SimpleInjector;
    using SimpleInjector.Integration.WebApi;

    public static class ContainerConfig
    {
        public static void Register(HttpConfiguration config)
        {
            Container container = new Container();
            InitializeContainer(container);
            container.RegisterWebApiControllers(config);
            container.Verify();
            config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        }

        private static void InitializeContainer(Container container)
        {
            container.RegisterWebApiRequest<IPrincipal>(() => 
                HttpContext.Current.User != null ? HttpContext.Current.User : Thread.CurrentPrincipal);
        }
    }
}
namespace PrincipalInjector
{
使用System.Security.Principal;
使用系统线程;
使用System.Web;
使用System.Web.Http;
使用SimpleInjector;
使用SimpleInjector.Integration.WebApi;
公共静态类容器配置
{
公共静态无效寄存器(HttpConfiguration配置)
{
容器=新容器();
初始化容器(容器);
container.RegisterWebApp控制器(配置);
container.Verify();
config.DependencyResolver=新的SimpleInjectorWebApidencyResolver(容器);
}
私有静态void InitializeContainer(容器)
{
container.RegisterWebApiRequest(()=>
HttpContext.Current.User!=null?HttpContext.Current.User:Thread.CurrentPrincipal);
}
}
}
样本控制器:

namespace PrincipalInjector.Controllers
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Security.Principal;
    using System.Web.Http;

    public class DefaultController : ApiController
    {
        private readonly IPrincipal principal;

        public DefaultController(IPrincipal principal)
        {
            this.principal = principal;
        }

        // GET api/default
        public IEnumerable<string> Get()
        {
            IList<string> roles = new List<string>();
            ClaimsIdentity claimsIdentity = null;

            if (this.principal.Identity.IsAuthenticated)
            {
                claimsIdentity = (ClaimsIdentity)this.principal.Identity;
                roles.Add("From injected principal");
            }
            else
            {
                claimsIdentity = (ClaimsIdentity)this.User.Identity;
                roles.Add("From ApiController.User");
            }

            if (claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.Role.ToString()).Count() > 0)
            {
                roles = roles.Union(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.Role.ToString()).Select(c => c.Value)).ToList();                
            }
            else
            {
                roles.Add("No roles found");
            }

            return roles;
        }
    }
}
namespace PrincipalInjector.Controllers
{
使用System.Collections.Generic;
使用System.Linq;
使用System.Security.Claims;
使用System.Security.Principal;
使用System.Web.Http;
公共类DefaultController:ApicController
{
私有只读i原则主体;
公共财务总监(主要负责人)
{
this.principal=principal;
}
//获取api/默认值
公共IEnumerable Get()
{
IList角色=新列表();
ClaimsIdentity ClaimsIdentity=null;
if(this.principal.Identity.IsAuthenticated)
{
claimsIdentity=(claimsIdentity)this.principal.Identity;
角色。添加(“来自注入主体”);
}
其他的
{
claimsIdentity=(claimsIdentity)this.User.Identity;
添加(“来自ApiController.User”);
}
if(claimsIdentity.Claims.Where(c=>c.Type==ClaimTypes.Role.ToString()).Count()>0)
{
roles=roles.Union(claimsIdentity.Claims.Where(c=>c.Type==ClaimTypes.Role.ToString()).Select(c=>c.Value)).ToList();
}
其他的
{
角色。添加(“未找到任何角色”);
}
返回角色;
}
}
}
示例控制器显示,注入的主体未经过身份验证,但本地ApiController.User主体是并包含用户角色。在上面的示例中,角色总是从路径“from ApiController.User”返回

有人知道为什么从simple injector获取Thread.CurrentPrincipal时声明不可用吗

干杯

编辑:在此处添加了人工设计的示例解决方案,该解决方案显示IPrincipal未注入角色详细信息,但本地ApiController用户主体:

进一步编辑:内联更新示例代码

进一步信息

如果我修改容器使用延迟加载,我可以从注入器获取主体

集装箱更换:

 container.RegisterWebApiRequest<Lazy<IPrincipal>>(() => new Lazy<IPrincipal>(() => Thread.CurrentPrincipal));
        private readonly Lazy<IPrincipal> principal;

        public DefaultController(Lazy<IPrincipal> principal)
        {
            this.principal = principal;
        }

        ...

        if (this.principal.Value.Identity.IsAuthenticated)
        {
            claimsIdentity = (ClaimsIdentity)this.principal.Value.Identity;
            roles.Add("From injected principal");
        }

        ...
container.RegisterWebApiRequest(()=>newlazy(()=>Thread.CurrentPrincipal));
控制器更改:

 container.RegisterWebApiRequest<Lazy<IPrincipal>>(() => new Lazy<IPrincipal>(() => Thread.CurrentPrincipal));
        private readonly Lazy<IPrincipal> principal;

        public DefaultController(Lazy<IPrincipal> principal)
        {
            this.principal = principal;
        }

        ...

        if (this.principal.Value.Identity.IsAuthenticated)
        {
            claimsIdentity = (ClaimsIdentity)this.principal.Value.Identity;
            roles.Add("From injected principal");
        }

        ...
私有只读惰性主体;
公共DefaultController(惰性主体)
{
this.principal=principal;
}
...
if(this.principal.Value.Identity.IsAuthenticated)
{
claimsIdentity=(claimsIdentity)this.principal.Value.Identity;
角色。添加(“来自注入主体”);
}
...

ApiController.User设置在请求的开头,该信息来自请求本身,而不是来自线程。我认为您应该改用
HttpContext.Current.User
。我不确定我是否100%正确地阅读了代码,但看起来您正在尝试在安装过程中获取当前用户。您可能想做的是获取请求的用户,该用户只有在管道中处理请求时才可用(通过OwinContext)。要获得每个请求的对象,您可能需要使用“app.CreatePerOwinContext(()=>new CurrentClaims(…);”嗨,Steven,感谢您的反馈,不幸的是,在这种情况下,这也不起作用。我已经添加了一个链接到一个精心设计的示例项目,以防您有时间查看它。它显示了注入API和本地API IPrincipal的区别。此外,一旦您进入请求管道并拥有IOwinContext,那么您就可以使用IOwinContext.Authentication.User来获取当前的索赔主体。您好,jaytre,感谢您的回复,我将对此进行研究,看看是否有帮助。我已经内联更新了示例代码,希望能够更清楚地了解正在发生的事情。