是否可以在 CustomAttribute 中重新绑定 IPrincipal? 来自 NinjectWebCommon.jsApiKeyAuthorizeAttribute.cs依赖链中的类构造函数

问题描述

背景

我们有一个 Web API 2 项目,我们正在将它变成我们的“公共 API”。在向我们的 API 发出请求时,我们使用自定义属性 (ApiKeyAuthorize) 根据 API 密钥查找用户,然后使用他们的信息创建 ClaimsPrincipal。

此外,依赖链中的一些类在它们的构造函数中有一个 IPrincipal,这要求我们绑定到 NinjectWebCommon.cs 中的 IPrincipal。我们将它绑定到 HttpContext.Current.User。

问题

问题是,一旦 Ninject 进行绑定,我就无法重新绑定 IPrincipal。触发我的属性逻辑后,HttpContext.Current.User 是正确的 ClaimsPrincipal,但注入的 IPrincipal 不会改变。我试过调用 kernal.Rebind 但这没有用。有没有一种方法可以重新绑定、延迟绑定,而无需使用 Lazy<T> 重写所有现有类,或者无需将所有 IPrincipal 替换为 Thread.CurrentUser

代码

来自 NinjectWebCommon.js

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            kernel.Bind<IPrincipal>().ToMethod(ctx => HttpContext.Current.User);

            RegisterServices(kernel);
            _kernel = kernel;
            return kernel;
        }

ApiKeyAuthorizeAttribute.cs

public override void OnAuthorization(HttpActionContext actionContext)
        {
            var apiKey = actionContext.Request.Headers.GetValues("apiKey")?.FirstOrDefault();

            // do lookup on the user and populate user object

            var identity = new ClaimsIdentity("Signature","subject","role");
            identity.AddClaim(new Claim("subject",user.Email));
            var principal = new ClaimsPrincipal(identity);
            actionContext.RequestContext.Principal = principal;
            Thread.CurrentPrincipal = newIdentity;

            // Is it possible to Rebind here???

            base.OnAuthorization(actionContext);
        }

        // I added this to try to rebind,but it doesn't work
        internal static void RebindCurrentUser(System.Security.Claims.ClaimsPrincipal newIdentity)
        {
            _kernel.Rebind<IPrincipal>().ToConstant(newIdentity);
        }

依赖链中的类构造函数

public class Foo
{
    private readonly ClaimsPrincipal _currentUser;
    public Foo(IPrincipal currentUser)
    {
       _currentUser = (ClaimsPrincipal)currentUser;
       // _currentUser doesn't have claims
       // Thread.CurrentUser does have claims
    }
}

解决方法

您绑定到 HttpContext.Current.User 但填充 actionContext.RequestContext.PrincipalThread.CurrentPrincipal。它们不是同一个对象。尝试在 HttpContext.Current.User 上设置新的主体。

另外,不确定您是否粘贴错了,但是 newIdentity 不存在于您的代码中。