在我的基于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控制器,它的ctor注入了一个服务类,而后者又将当前用户注入其中,堆栈看起来像这样......
class SomethingController : ApiController {
public SomethingController(ISomethingService service) { ... }
}
class SomethingService : ISomethingService {
public SomethingService(User user) { ... }
}
由于某些奇怪的原因,当我将当前用户注入服务构造函数时,用户尚未经过身份验证。
在认证提供程序(aspnet标识)完成其工作并确认用户是谁之前,似乎正在构建堆栈。
稍后,当从控制器进行实际服务调用时,用户将被验证,并且我给出的用户对象是访客,而不是发出呼叫的实际用户。
我的理解是,在认证和确定请求/用户详细信息完成之前,没有构建控制器。
如何确保每次都正确地将经过身份验证的当前用户传递给我的业务服务(仅在进行身份验证之后)?
编辑:
我想我发现了问题:dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle它看起来像控制器及其所有依赖项都是在运行任何auth逻辑之前创建的。我想问题就变成......我可以强制AuthoriseFilter在构造控制器之前运行并确认用户身份。
这有点改变我的问题:
如何确保在构建控制器及其所有依赖项之前进行身份验证?
编辑2:答案 - 不理想,但答案......
有更多rep的人可以解锁这个问题吗,这不是另一个问题的重复,OP询问Ninject的基本用法我询问WebApi生命周期以及如何在会话之前获取与会话相关的上下文因当前的要求而闻名。
好的我不喜欢这个答案,但它是一个解决方案。
如果其他人有更好的,我很乐意听到它......
如果我将服务构造函数更新为此...
class SomethingService : ISomethingService {
public SomethingService(IKernel kernel) { ... }
}
...当我来运行我的服务代码时,我将内核放入本地字段......
public void Foo() {
var user = kernel.Get<User>();
}
......这意味着......
我在请求生命周期中让用户进行身份验证和授权,并正确构建堆栈。
现在,如果我要求用户,当规则运行时,HttpContext正确显示正确的用户详细信息。
它有效但......
这是DI反模式类型的行为,我不喜欢它,并且更愿意找到一个解决方案,这意味着我可以在那里验证用户然后如果它还没有发生但它基本上意味着复制代码WebApi堆栈已经具有(这可能意味着它更容易),并且无论如何都将发生,基本上导致身份验证过程发生两次。
如果没有这样的解决方案......这是一个“半”合理的解决方法。
答案 0 :(得分:1)
已经有一段时间,但我后来找到了答案。
问题在于,虽然我提供了一些auth信息,其形式是提供作为标头值提供的身份验证令牌,但我试图构建有关用户的信息,我可能在请求期间甚至不需要它。 / p>
我想确保我的所有业务服务都位于处理请求的控制器后面,当前用户只需要auth信息,以便auth信息可用于确定和做出与安全相关的决策(例如,如果合适的话,获取用户。)
最后,我创建了一个IoC绑定,可以检查我的owin上下文,并询问auth信息,然后根据需要将该auth信息注入我的控制器/服务。
从那里起,我至少得到了做出关键决定所需的背景信息。