5

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

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

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

容器注册:

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.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;
        }
    }
}

示例控制器显示注入的主体未经过身份验证,但本地 ApiController.User 主体是并且包含用户角色。在上面的示例中,角色总是从路径“From ApiController.User”返回。

有人知道为什么从简单的注入器获取 Thread.CurrentPrincipal 时声明不可用吗?

干杯

编辑:在此处添加了人为的示例解决方案,显示 IPrincipal 未注入角色详细信息,但本地 ApiController 用户主体执行:http ://www.filedropper.com/principalinjector

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

更多信息

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

容器变化:

 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");
        }

        ...
4

0 回答 0