基本上,我正在尝试获取当前访问 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");
}
...