我有一个体面的网络应用程序,我想制作多客户端。所以,我有一个User表,我的计划是将ClientId字段添加到该表,然后我可以限制用户只看到他们所属的客户端的数据。
在一个理想的世界中,我想尝试在最低级别烘焙安全性,这样就很难意外地创建一个会导致客户端看到其他客户端数据的功能。因此,当我在控制器中使用服务时,而不是每次都必须传递clientId:
var messages = _messageService.GetMessagesByType(clientId, type);
这是自动的:
var messages = _messageService.GetMessagesByType(type);
我正在使用Ninject将我的服务注入控制器:
public static void RegisterTypes(IKernel kernel)
{
kernel.Bind<IMessageService>().To<MessageService>();
}
我现在的思考过程是将当前用户的clientId存储为会话变量,然后以某种方式将它们注入IServices,然后再将它们在控制器中使用。
但是,我假设在App_Start上调用一次RegisterTypes方法,那么在调用一个动作时如何进行注入呢?或者是否有更好的方法来实现我的目标?
答案 0 :(得分:1)
可悲的是,我对网络开发和特殊的asp.net-mvc知之甚少。但是,以下可能是您可以接受的解决方案:
(注意:我认为客户端ID属于ClientId
类型。请参阅here了解原因。)
给出:
public class MessageService : IMessageService
{
public MessageService(ClientId clientId,...) {...}
...
}
你可以定义一个绑定:
kernel.Bind<IMessageService>().To<MessageService>
.WithParameter(new TypeMatchingConstructorArgument(
typeof(ClientId),
(ctx, target) => (ClientId)HttpContext.Current.Session["clientId"]));
将HttpContext.Current.Session["clientId"]
的值注入到ClientId
的构造函数中的MessageService
类型的参数中。
您可以使用TypeMatchingConstructorArgument
参数代替ConstructorArgument
,而不是参数名称而不是参数类型。
现在为了更进一步,所以它也适用于其他服务,我们也可以简单地做:
kernel.Bind<ClientId>()
.ToMethod(ctx => ClientId)HttpContext.Current.Session["clientId"]);
kernel.Bind<IMessageService>().To<MessageService>();
注意:您可能需要考虑添加(对绑定)验证是否存在会话以及是否设置了clientId。
另请注意:在实例化服务之前,您需要注意clientId
实际已知(放在会话中)(=由控制器或其中一个依赖项请求)。