将身份用户传递给服务

3
我们正在开发一个Web应用程序,用户可以在其中注册订单、客户等,并随后对其进行查看。我们有一些服务用于MVC控制器与Web UI接口。现在我们面临多个用户的问题:每个服务应该提供当前授权用户ID,因此所有操作(CRUD和业务逻辑)只允许该用户ID执行。如何传递它呢?我考虑将参数传递给我的IDataService(服务基类),这是由WhateverController实例化的,后者又可以访问User.Identity.GetUserId()方法,但由于我正在使用IoC容器(Ninject),我不知道怎么做。我猜IDataService需要一个IUserInfoProvider的引用,以便它可以调用IUserInfoProvider.GetUserId()。然后,我可以以某种方式注入一个基于Identity和具有当前Web上下文信息的实现,基本上与必须实例化Controller的方式相同。
问题是:如何获取这些数据?
当然,更简单的解决方案是在每个控制器构造函数中手动执行此操作,但应该有一种更自动化和优雅的方式来解决这个问题。
编辑:经过进一步的研究,感谢Cuong Le的答案,我必须问的问题实际上是“如何从当前上下文注入UserManager?”。
但是,为了将我的服务层与MVC分离,我创建了一个IUserInfoProvider,它提供对已验证的用户数据的访问。基于Identity和UserManager的实现位于Web UI(MVC)项目中,因此它具有像Cuong Le建议的IPrincipal和ApplicationUserManager一样的内容,所有这些都使用Ninject注入。
以下接口抽象了来自Identity和UserManager的用户信息。
public interface IUserInfoProvider<T>
{
    string GetUserId();
    T GetUserData();
}

这里是在MVC项目中使用Identity和UserManager实现的方法。
public class IdentityUserInfoProvider : IUserInfoProvider<DatosEmpresa>
{
    private readonly ApplicationUserManager _userManager;
    private readonly IPrincipal _user;

    public IdentityUserInfoProvider(ApplicationUserManager userManager, IPrincipal user)
    {
        _userManager = userManager;
        _user = user;
    }

    public string GetUserId()
    {
        return _user.Identity.GetUserId();
    }

    public DatosEmpresa GetUserData()
    {
        return _userManager.FindById(_user.Identity.GetUserId()).DatosEmpresa;
    }
}

还有Ninject配置部分

kernel.Bind<IUserInfoProvider<DatosEmpresa>>().To<IdentityUserInfoProvider>();

kernel.Bind<IPrincipal>()
        .ToMethod(ctx => HttpContext.Current.User)
        .InRequestScope();

kernel.Bind<ApplicationUserManager>()
        .ToMethod(ctx => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>())
        .InRequestScope();

那么我可以在任何服务对象中使用IUserInfoProvider,从而获取正确的用户信息。


我并没有完全理解问题所在,但通常我会让所有的控制器都继承一个名为“Base”的类,在那里你可以有一个名为UserId的属性,它的get方法是返回User.Identity.GetUserId()。 - Ziv Weissman
我希望我的IDataService派生服务可以访问当前身份用户ID,而无需从每个实例化这些服务的控制器中专门设置它。 - Arturo Ribes
你能从这些服务中访问HttpContext.Current.Session吗?例如,可以查看此链接 - https://dev59.com/LXHYa4cB1Zd3GeqPLXP5 - Ziv Weissman
你能直接调用API吗?例如编写一个Winform应用程序来调用API?如果可以,您是如何处理这些情况下的身份验证的?MVC和WebAPI站点的IIS身份验证设置是什么(匿名/表单/Windows身份验证)? - freedomn-m
1个回答

5
简单的解决方案是将 IPrincipal 放入 NInject 容器中:
kernel.Bind<IPrincipal>().ToMethod(context => HttpContext.Current.User);

所以在您的ServiceBase中,您可以通过属性或构造函数注入IPrincipal,就像这样:

class ServiceBase
{
    [Inject]
    public IPrincipal User { get; set; }
}

现在,您可以从此属性中获取信息。

1
谢谢你的提示,我把你的答案作为我的解决方案的起点。请查看更新后的帖子以获取更多细节。 - Arturo Ribes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接