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

本文关键字:注入 用户 控制器 服务 请求 | 更新日期: 2023-09-27 18:15:33

在我基于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 SomethingController : ApiController {
     public SomethingController(ISomethingService service) { ... }
}
class SomethingService : ISomethingService {
     public SomethingService(User user) { ... }
}

令人沮丧的是,由于一些奇怪的原因,当我将当前用户注入到服务构造函数中时,用户还没有经过身份验证。

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

稍后,当从控制器发出实际的服务调用时,用户经过身份验证,并且我所给出的用户对象是针对guest的,而不是发出呼叫的实际用户。

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

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

编辑:

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

这把我的问题变成了:

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


编辑2:一个答案-不理想,但一个答案…

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


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

如果有人有更好的,我很乐意听一听……

如果我更新我的服务构造函数为…

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

…当我开始运行我的服务代码时,我把内核放到一个本地字段中…

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

…这意味着…

我在请求生命周期的某个点获得用户,此时身份验证和授权已经发生,堆栈已经正确构造。

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

可以,但是…

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

如果没有这样的解决方案……这是一个"半"合理的解决方法。

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

这是一段时间,但我后来找到了这个问题的答案。

问题是,虽然我有一些身份验证信息的形式,说一个身份验证令牌作为头值提供,我试图构建关于用户的信息,我可能甚至不需要它在请求期间。

我想确保位于处理请求的控制器后面的所有业务服务都将被提供给当前用户,而实际上它们只需要身份验证信息,以便身份验证信息可以用于确定和做出与安全相关的决策(例如,如果合适的话获取用户)。

最后,我创建了一个IoC绑定,它可以检查我自己的上下文并请求验证信息,然后我将根据需要将该验证信息注入到我的控制器/服务中。

从那里我至少有了上下文信息,我需要做出关键的决定。