Ninject InRequestScope没有为每个Web请求创建新实例

时间:2016-06-07 11:25:46

标签: c# asp.net-mvc ninject

我在我的mvc应用程序中使用带有AspNet标识的ninject

在我的全局asax中,我有以下代码行

kernel.Bind<IIdentityManager>().To<IdentityManager>().InRequestScope().WithConstructorArgument("conn", idConnString);

每当向控制器发出新请求时,都应该创建上述类的新实例。

然而,这并没有发生。断点显示上述类的构造函数仅在网站加载时被调用一次,并且在我刷新页面或发出新请求时永远不再被命中(它被注入到每个页面请求检查的类中)声明并因此授权或拒绝用户访问他们所请求的页面。因此,支持identitymanager的数据库连接上下文保持不变,并且永远不会根据请求重新加载。因此,它永远不会对网站外部发生的声明进行任何更改,如果在每个请求上创建了一个新的IdentityManager实例,就会发生这种情况,因为我希望它能够给出上述绑定。

非常感谢任何建议。

编辑以添加更多代码。 (注意我删除了与此特定问题无关的代码以使其更短)

我的Global.asax

protected override IKernel CreateKernel()
      {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        kernel.Bind<IVariables>().ToConstructor<Variables>(context => new Variables(AppSettingKeys.NRDAWebServer)).InRequestScope();

        var variables = kernel.Get<IVariables>();


        var masterPassword = VBHelperCore.Encryptor.EncDec.Decrypt(File.ReadAllBytes(AppSettingKeys.ConfigSettingsKeys.ConfigLocation + AppSettingKeys.SQLConnection.NRDAMasterUserName),
                AppSettingKeys.HexString);
        var s3ConnString = @"Data Source=" + variables.Get(AppSettingKeys.SQLConnection.NRDAMasterSQLServer, null) + @";Initial Catalog=" + variables.Get(AppSettingKeys.SQLConnection.NRDAMasterDB, null) +
                                                                            ";User ID=" + variables.Get(AppSettingKeys.SQLConnection.NRDAMasterUserName, null) + ";Password=" +
                                                                            masterPassword +
                                                                            ";Trusted_Connection=False;MultipleActiveResultSets=True;";
        var idConnString = s3ConnString;

         kernel.Bind<IAuthenticationFilter>().To<NrdaAuthenticationAttribute>().InRequestScope();

        kernel.Bind<IIdentityManager>().To<IdentityManager>().InRequestScope().WithConstructorArgument("conn", idConnString);

        kernel.Bind<INrdaClaimsTransformer>().To<NrdaClaimsTransformer>().InRequestScope();

        GlobalConfiguration.Configuration.DependencyResolver = new Ninject.WebApi.DependencyResolver.NinjectDependencyResolver(kernel);

        return kernel;
    }

这实质上加载配置变量以获取带有密码的连接字符串,然后将IdentityManager的新实例与传递给其构造函数的连接字符串绑定。

我已经定义了一个ActionFilter

public class NrdaAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
    [Inject]
    public INrdaClaimsTransformer ClaimsTransformer{ private get; set; }
    [Inject]
    public ILogger Log { get; set; }
    public void OnAuthentication(AuthenticationContext filterContext)
    {
        try
        {
            var user = filterContext.HttpContext.User;
            if ((user != null && user.Identity.IsAuthenticated))
            {
                ClaimsPrincipal currentPrincipal = ClaimsPrincipal.Current;
                ClaimsPrincipal tranformedClaimsPrincipal = ClaimsTransformer.Authenticate(string.Empty, currentPrincipal);
                Thread.CurrentPrincipal = tranformedClaimsPrincipal;
                HttpContext.Current.User = tranformedClaimsPrincipal;
            }
            else
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }
        catch (SecurityException ex)
        {
            Log.Error(ex, "Security error" + ex.Message, null);
        }
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {


    }



}

所有控制器都有,所以每次访问任何控制器时都会调用此过滤器(所以每次请求都是如此)

[NrdaAuthentication]

过滤器使用内核绑定的Claims Transformer

public class NrdaClaimsTransformer : ClaimsAuthenticationManager, INrdaClaimsTransformer
{
    [Inject]
    public IIdentityManager IdentityManager { private get; set; }

    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {

        var ret = !incomingPrincipal.Identity.IsAuthenticated
             ? base.Authenticate(resourceName, incomingPrincipal)
             : DressUpPrincipal(incomingPrincipal);
        return base.Authenticate(resourceName, ret);
    }

    private ClaimsPrincipal DressUpPrincipal(ClaimsPrincipal incomingPrincipal)
    {



        var user = IdentityManager.GetByUsername(incomingPrincipal.Identity.Name);
        return null //code removed to simplify example
    }
}

显然我已经削减了很多代码以简化,但由于ninject绑定都被设置为InRequestScope(),我希望在每个新请求上调用IdentityManager的构造函数。但事实并非如此。断点显示它仅在网站首次启动时调用,之后再次调用,因此它必须在每个Web请求中使用相同的实例,而不应该

编辑2

好的我觉得我发现了问题。似乎因为InRequestScope在自定义授权属性中不起作用。或者实际上我尝试过的任何其他范围函数。我假设这是因为属性实例被加载到用户会话的内存中,因此注入的类永不过期,因此不需要由ninject重新加载。当我通过使用控制器调用注入的类来进行测试时,在操作中它可以正常工作。现在我只需要在属性中加载一个新的identitymanager实例而不是ninject版本

0 个答案:

没有答案