如何将当前用户的请求注入到控制器/服务中?

How to inject the current user for a request in to a controller / service?

在我基于 WebApi 的应用程序中,我有一个 Ninject 绑定,用于将当前用户注入到事物中...

Bind<User>().ToMethod((context) =>
{
    User result = new User { UserName = "Guest" };

    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        var service = Kernel.Get<IUserService>();
        var user = service.GetAll().FirstOrDefault(u => u.UserName == HttpContext.Current.User.Identity.Name);
        return user;
    }

    return result;
});

很简单吧?

然后我有一个 webApi 控制器,它有一个服务 class 注入到它的 ctor,反过来又将当前用户注入到它,堆栈看起来像这样......

class SomethingController : ApiController {
     public SomethingController(ISomethingService service) { ... }
}

class SomethingService : ISomethingService {
     public SomethingService(User user) { ... }
}

令人沮丧的是,当我将当前用户注入服务构造函数时,由于某些奇怪的原因,用户尚未通过身份验证。

似乎在身份验证提供程序 (aspnet 身份) 完成工作并确认用户身份之前正在构建堆栈。

稍后,当从控制器发出实际服务调用时,用户已通过身份验证,我得到的用户对象是针对来宾的,而不是发出调用的实际用户。

我的理解是,在完成身份验证和确定请求/用户详细信息之前,不会构建控制器。

如何确保当前的、经过身份验证的用户每次都正确地传递到我的业务服务(仅在进行身份验证之后)?

编辑:

我想我发现了问题:dotnetcurry。com/aspnet/888/aspnet-webapi-message-lifecycle 看起来控制器及其所有依赖项都是在任何身份验证逻辑 运行 之前创建的。我想问题就变成了......我可以强制 AuthoriseFilter 运行 并在构建控制器之前确认用户身份吗?[=​​14=]

这将我的问题稍微改变为:

如何确保在构造控制器及其所有依赖项之前进行身份验证?


编辑 2:答案 - 不理想但答案......

请有更多代表的人解开这个问题,这不是另一个问题的重复,OP 在询问 Ninject 的基本用法我在询问 WebApi 生命周期以及如何获取会话当前请求已知会话之前的相关上下文。


好吧,我不喜欢这个答案,但它是一个解决方案。

如果有人有更好的,我很想听听...

如果我将我的服务构造函数更新为此...

class SomethingService : ISomethingService {
     public SomethingService(IKernel kernel) { ... }
}

... 然后我将内核放入本地字段,当我到达 运行 我的服务代码时 ...

  public void Foo() {
      var user = kernel.Get<User>();
  }

...这是什么意思...

我在发生身份验证和授权的请求生命周期点获取用户,并且正确构建了堆栈。

现在,如果我请求用户,当规则 运行s HttpContext 正确显示正确的用户详细信息时。

它有效但是...

这在很大程度上是 DI 反模式类型的行为,我不喜欢它并且更愿意找到一个解决方案,这意味着我可以在那里对用户进行身份验证然后如果它还没有发生但它基本上意味着复制 WebApi 堆栈已经拥有的代码(虽然这可能意味着它更容易)并且无论如何都会发生,基本上导致身份验证过程发生两次。

在没有这样的解决方案的情况下......这是一个 "semi" 合理的解决方法。

已经有一段时间了,但后来我找到了答案。

问题是,虽然我有一些身份验证信息,例如作为 header 值提供的身份验证令牌,但我试图构建有关用户的信息,但我什至可能不需要它在请求期间。

我想确保我所有位于处理请求的控制器后面的业务服务都将提供给当前用户,而实际上他们只需要授权信息,以便授权信息可用于确定和使安全相关决策(例如在适当的情况下获取用户)。

最后我着手创建一个 IoC 绑定,它可以检查我的 owin 上下文并要求它提供身份验证信息,然后我会根据需要将该身份验证信息注入我的控制器/服务。

从那里我至少获得了做出关键决策所需的上下文信息。