0

鉴于:

我已经创建HashCaptcha类。Hash创建表单标记。Captcha使用Graphics类来创建图像。自定义会话服务包装类用于处理$_SESSION超全局数据结构。

设想:

我使用依赖注入容器。因此,我想知道在哪里定义可公开访问的 HTML 表单的实例化Captcha和实例化。Hash

假设 1:您应该注入一个子节点,Hash因为需要访问来存储(根据 HTTP 请求)和验证(根据 HTTP 响应)CSRF 令牌和 CAPTCHA 答案。视图不应该访问会话数据结构。CaptchaModel$_SESSION

假设 2:您应该注入HashCaptcha的子代,View因为生成 CSRF 令牌和验证码实际上是 View表示逻辑的一部分,即使它们的验证发生在Model. View允许从 a 直接或间接访问会话数据结构。

第一个假设似乎是答案,但我想确定一下。

摘要示例:

$session = new Session(); // A custom wrapper class
$hash = new Hash();
$graphics = new Graphics();
$captcha = new Captcha($graphics);


$model = new ContactModel($session, $hash, $captcha);

或者

$view = new ContactView($session, $hash, $captcha);
4

2 回答 2

2

注意#1:我认为您应该通读这篇文章。我将强调这个答案的核心部分:“模型不是一个类或任何单个对象”

注意#2: IMO 这个问题是 Web MVC 实现所固有的。第一部分是我将如何解决这个问题;下面从概念上描述为什么会出现这个问题。

我的回答是:两者都不是

MVC架构分为2层:模型层和表示层。服务对象(这些位于模型层中)应将相关的验证码信息实例化/保存到客户端状态。由于这很可能是一个 Web 应用程序,因此表示层(特别是视图对象)将需要从模型层请求此客户端状态。这是否通过服务对象或专门为客户端状态响应量身定制的特定于表示的数据访问对象发生取决于您的实现和最适合。在这里,在视图中,我将通过另一个数据访问对象或(Cookie/Session)Response抽象*。通过这种方式,视图不会“访问”会话数据结构,而是利用一个组件(表示层 DAO 或(Cookie/Session)Response抽象*)来完成这项工作。虽然我们不认为 cookie/sessions 是表示(“它们不是可视的”),但表示层负责响应,cookies/sessions 就是这样。

我很难具体推测这将如何在您的框架中进行,因为模型层似乎存在混淆。您ContactModel当然希望哈希/验证码来保存客户端状态。您的视图不需要这些,而是​​一种额外的机制,以 cookie/会话的形式“响应”客户端状态对 HTTP 请求。

* Symfony 通常对此很有帮助。我同时使用了表示层 DAO 和 SymfonyHttpFoundation对象,这可能是多余的。

从概念上讲:会话作为状态与响应

您在这里解决的基本问题是特定于 Web MVC 实现的。Web MVC 中的表示层处理“请求”(委托给控制器)​​并呈现“响应”(由视图决定)。在 HTTP 中,cookie 和会话随请求一起发送并在响应中更改。这嵌入在 HTTP 请求/响应性质中。

如果我们将会话/cookie 保存在模型层中,我们就使模型层依赖于 HTTP 并允许它“响应”请求。即使我们抽象了超全局变量和“注入”抽象(如 Symfony cookie/会话对象),也存在对请求/响应实现的 cookie/会话的内在依赖。你可以在模型层做这一切,但我不喜欢。换句话说,虽然模型负责跟踪状态,但 cookie/会话状态实际上是对请求的响应。

“但这是有漏洞的逻辑,因为您在表示层中保存状态”

我认为您可以将所有方法视为有些“漏洞”,这只是最具凝聚力的方法。如果您将 cookie/会话视为状态,那么我们肯定会在表示层中“保存”状态。如果您将它们视为响应,它们确实在 MVC 眼中,那么这根本不是泄漏的。我认为在模型层发送响应(保存会话/cookie 状态)更糟糕。

于 2018-10-22T06:18:48.637 回答
0

:您应该在“模型”中生成 CSRF 令牌和 CAPTCHA 值。

原因:这些值的目的是作为对您的业务逻辑的约束,而不仅仅是在“视图”中显示值或控件。如果“视图”生成表单令牌和验证码挑战值,则必须将它们传回“模型”(一种或另一种方式)。这与潮流背道而驰。

虽然假设二是可行的,但它赋予 View 的职责是它没有完全完成。具体来说,视图永远不会负责验证表单令牌或验证码答案。

视图可以以虚拟方式将表单标记和验证码挑战插入 HTML 表单模板(例如)。这是真的,但是现在“视图”将负责将答案保存到某种持久存储中,而“模型”只会检索和验证它们。

因此,会话存储将充当“视图”和“模型”之间的后端通道,因此将它们耦合起来(即使使用某种会话服务包装器)。“视图”应该通过“模型”传递数据,但如果允许“视图”生成表单标记和验证码答案值,这实际上就是发生的事情。

这就是我的回答。我欢迎您的评论和批评。

于 2018-10-22T15:35:21.847 回答