【问题标题】:Using Ninject in asp.net mvc GenerateUserIdentityAsync to add custom claim在 asp.net mvc GenerateUserIdentityAsync 中使用 Ninject 添加自定义声明
【发布时间】:2017-04-04 11:29:45
【问题描述】:

当用户登录(从 Google 外部登录)时,我需要通过执行对数据库的读取并添加返回的值来添加自定义声明。我正在使用 Ninject 进行依赖注入,以将具有接口的控制器注入到我的业务层服务中。

所以我找到了 identityModels.cs 方法来添加声明:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here

        string userId = userIdentity.GetUserId();

        //var _iUserBLL = (IUserBLL)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IUserBLL));
        //UserBO objUser = _iUserBLL.GetById(userId);

        //userIdentity.AddClaim(new Claim("Value1", objUser.Value1));
        //userIdentity.AddClaim(new Claim("Value2", objUser.Value2));
        return userIdentity;
    }

这里 System.Web.Mvc.DependencyResolver.Current.GetService 行失败并导致它崩溃。这适用于其他地方,我也尝试过与注入控制器相同的方法,例如:

public class MyController : Controller
{
    private readonly IUserBLL _iUserBLL;

    public MyController (IUserBLL iUserBLL)
    {
        _iUserBLL = iUserBLL;
    }
}

甚至:

[Inject]
    public IUserBLL _iUserBLL { get; set; }

但在 GenerateUserIdentityAsync 方法中使用时,_iUserBLL 为空。有什么想法可以在这里注入我的 IUserBLL 来进行自定义数据库调用吗?

更多信息 - 如果您不熟悉此方法,它是在具有个人用户帐户的 Visual Studio 项目中生成的身份代码的一部分。

全班是这样的:

public class ApplicationUser : IdentityUser
{
     public async Task<ClaimsIdentity> 
       GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
     {
        ...
     }
}

所以我在这里尝试了构造函数,它不起作用:

public class ApplicationUser : IdentityUser
    {
        private readonly IUserBLL _iUserBLL;

        public ApplicationUser (IUserBLL iUserBLL)
        {
            _iUserBLL = iUserBLL;
        }
...
}

IdentityUser 在预先提供的 identity.entityframework 类的内部工作中声明,并从我无法编辑的内部调用,所以我很困惑如何处理这个?

感谢您的回复 Sam,它让我找到了解决方案。这是我最终得到的代码。我在使用静态“Create”方法时遇到了问题,所以我改用了 [Inject] 属性。有没有办法改变静态“创建”方法以在构造函数中使用 IUserBLL?这是我正在工作的代码:

在 App_Start/IdentityConfig.cs 中

// Configure the application sign-in manager which is used in this application.
    public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
    {
        [Inject]
        public IUserBLL _iUserBLL { get; set; }

        public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
            : base(userManager, authenticationManager)
        {
        }

        public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
        {

            var userIdentity = user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);

            UserBO objUser = _iUserBLL.GetById(user.Id);

            userIdentity.Result.AddClaim(new Claim("Claim1", objUser.Value1));
            userIdentity.Result.AddClaim(new Claim("Claim2", objUser.Value2));

            return userIdentity;

        }

        public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
        {
            return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
        }
    }

在我的 NinjectWebCommon.cs 中,我还包括这些行,是我所有绑定的额外内容:

private static void RegisterServices(IKernel kernel)
        {
kernel.Bind<System.Security.Principal.IPrincipal>().ToMethod(context => HttpContext.Current.User).InRequestScope();
            kernel.Bind<ApplicationUserManager>().ToMethod(context => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()).InRequestScope();
            kernel.Bind<ApplicationSignInManager>().ToMethod((context) =>
            {
                var cbase = new HttpContextWrapper(HttpContext.Current);
                return cbase.GetOwinContext().Get<ApplicationSignInManager>();
            });
...
}

【问题讨论】:

  • 如果方法是从可以成功注入相关接口的地方调用的,则将其作为方法参数传递
  • 为什么不在包含 GenerateUserIdentityAsync 方法的类中为 IUserBLL 进行构造函数注入,就像在构造函数中一样?
  • 干杯,我在上面添加了更多信息。理想情况下,我只想拥有public class ApplicationUser : IdentityUser { [Inject] public IUserBLL _iUserBLL { get; set; } 但 _iUserBLL 始终为空。我是否在 NinjectWebCommon.cs 中遗漏了一些东西来告诉 Ninject 注入这个?

标签: asp.net-mvc asp.net-identity-2 ninject.web.mvc


【解决方案1】:

ApplicationUser 是一个实体对象,这种对象负责保存数据而不是做逻辑。如果您在UserManager 而不是ApplicationUser 中添加自定义声明会更好。考虑一下:

public class ApplicationUserManager: UserManager<ApplicationUser>
{
    private readonly IUserBLL _iUserBLL;

    public ApplicationSignInManager(IUserStore<ApplicationUser> store, 
         IUserBLL iUserBLL)
        : base(store)
    {
        // if you already fully integrated Identity with ninject, 
        // ninject could automatically resolve this for you.
        _iUserBLL=iUserBLL;
       // other configurations here
    }

    public override async Task<ClaimsIdentity> CreateIdentityAsync(
         ApplicationUser user, 
         string authenticationType)        
    {
        var userIdentity=await base.CreateIdentityAsync(user, authenticationType);
        UserBO objUser = _iUserBLL.GetById(userId);

        userIdentity.AddClaim(new Claim("Value1", objUser.Value1));
        userIdentity.AddClaim(new Claim("Value2", objUser.Value2));

        return userIdentity;
    }
}

【讨论】:

  • 谢谢 Sam,这对我有用,我已经用我最终得到的代码更新了帖子。由于静态创建方法,我不得不使用 [Inject],这看起来可以吗?
  • 因为 ApplicationSignInManager 不需要在 Owin 上下文中注册。您可以通过让 ninject 初始化 ApplicationSignInManager 而不是 Owin 上下文来摆脱静态方法,并从 Startup.Auth.cs 文件中删除其注册。
  • 虽然更改在登录时适用于 IdentityConfig 方法,但调用的是 IdentityModels 方法来重新生成身份(来自 Startup.Auth),因此在发生这种情况时我会丢失用户名。所以我回到第一方,如何注入 ApplicationUser 方法以在 IdentityModels.cs 中使用我的 IUserBLL,GenerateUserIdentityAsync?
  • @Bluemoon 因此,不要在SignInManager 中添加您的额外声明,然后将它们放在ApplicationUserManager 中。请参阅我的更新帖子。
猜你喜欢
  • 2018-01-10
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 2019-01-28
  • 2019-06-29
  • 2018-07-05
  • 1970-01-01
相关资源
最近更新 更多