我假设您正在谈论一种情况,即未经身份验证的用户可以尝试导航到通常需要身份验证的页面,但无需先完成登录过程。然后,Ninject 将无法将当前用户对象注入控制器,因为它尚不为人所知,并且会引发异常。
我可以看到 2 个选项:
第一个选项不是注入当前用户,而是创建一个工厂或提供者来检索当前用户详细信息并注入它。然后控制器可以调用提供程序来获取当前用户,如果用户不可用,您可以重定向到登录页面。
public OrdersController(IUserProvider userProvider)
{
this.userProvider = userProvider
}
public void DoSomething()
{
var user = this.userProvider.GetCurrentUser();
if (user == null)
RedirectToLogin();
// continue doing something
}
public class UserProvider : IUserProvider
{
public User GetCurrentUser() { ... }
}
此选项的问题是您可能需要在许多控制器中执行此操作(这是一个“横切关注点”),并且您不想一遍又一遍地重复执行重定向的代码。相反,第二种选择是使用装饰器设计模式创建一个拦截器,在转发到真实控制器之前检查登录用户。
我过去做过类似的事情的方式是使用Ninject Interception Extension创建一个属性来标记哪些控制器需要身份验证,如下所示(位 psuedo-codey):
public class AuthenticationInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
bool authenticated = // ... get the current user ...
if (authenticated)
invocation.Proceed();
else
RedirectToLoginPage(); // however you want to do this
}
}
public class RequiresAuthenticationAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<AuthenticationInterceptor>();
}
}
[RequiresAuthentication]
public class OrdersController : IOrdersController
{
// assume you've already been authenticated
}
RequiresAuthentication
每当创建装饰的类并检查当前用户凭据时,都会自动创建拦截器。如果它们无效,请求将被转发到登录页面,否则将照常继续。然后可以编写和测试这个拦截器一次,同时在许多地方使用,而无需重复代码。