在应用程序作用域中存储 CFC 用户内容处理程序是否安全?



我读过很多关于在应用程序范围内存储CFC的文章,我知道如果CFC存储数据,那么它不应该在应用程序范围内。所有执行非实用性操作的 CFC 都会存储数据 - 当您传入用户名或电子邮件地址等参数时 - 因此我不知道何时以及何时不使用非实用 cfc 的应用程序范围。

我的问题是我有一个大约 500 行代码的posthandler.cfc组件来处理来自用户的帖子(就像 SO 会处理本网站上发布的每个问题一样)。posthandler.cfc组件:

  • "清理"用户提交的任何图像和文本
  • 将图像放在正确的文件夹中
  • 将所有文本写入数据库
  • 返回可在其中查看帖子的 URL

返回的 URL 由一个简单的 Jquery ajax 调用接收,该调用将用户重定向到 URL。

这在网站上经常发生,目前正在为每个帖子创建一个新的 CFC 实例。 将其放在应用程序范围内而不会导致比赛/锁定条件是否安全?

只是传入参数不会"保存"任何东西。从概念上讲,每个线程都有自己的argumentslocal作用域,对任何其他线程都不可见,并且在函数退出时不复存在。所以从这个角度来看,没有冲突。

此外,存储数据并不意味着将其保存到数据库表中。 它是指通过在共享作用域/对象/等中存储数据来维护状态的组件。"共享"意味着资源可供其他线程访问,并且可能同时被多个线程修改,从而导致争用条件。

例如,以这个(人为的)组件函数为例,该函数在variables范围内"保存"信息。 如果每次都创建该组件的新实例,则该函数是安全的,因为每个请求都会获取自己的实例和要使用的variables范围的单独副本。

public numeric function doStuff( numeric num1, numeric num2 ) {
variables.firstNum = arguments.num1 * 12;
variables.secondNum = arguments.num2 * 10;
return variables.firstNum / variables.secondNum;
}

现在,使用相同的组件并将其放入应用程序范围。它不再安全。一旦将其存储在application作用域中,实例(及其variables)也将成为应用程序作用域。因此,当函数将数据"保存"到variables范围时,它实际上是在更新application变量。显然,这些不是线程安全的,因为所有请求都可以访问。因此,多个线程可以轻松地同时读取/修改相同的变量,从而导致竞争条件。

// "Essentially" becomes this .... 
public numeric function doStuff( numeric num1, numeric num2 ) {
application.firstNum = arguments.num1 * 12;
application.secondNum = arguments.num2 * 10;
return application.firstNum / application.secondNum;
}

此外,正如James A Mohler指出的那样,当您省略范围时,也会发生同样的问题。声明没有作用域的函数变量不会使其成为函数的本地变量。它使其成为默认作用域的一部分:variables-(创建与上述相同的线程安全问题)。当开发人员忘记限定单个查询变量甚至循环索引的作用时,这种行为导致了许多线程错误。因此,请务必明确限定每个函数变量的范围。

// Implicitly creates "variables.firstNum" and "variables.secondNum"
public numeric function doStuff( numeric num1, numeric num2 ) {
firstNum = arguments.num1 * 12;
secondNum = arguments.num2 * 10;
return firstNum / secondNum;
}

除了添加锁定之外,这两个示例都可以通过显式使用local范围来使线程安全。通过将数据存储在瞬态local作用域中,它对其他线程不可见,并且在函数退出后将不复存在。

public numeric function doStuff( numeric num1, numeric num2 ) {
local.firstNum = arguments.num1 * 12;
local.secondNum = arguments.num2 * 10;
return local.firstNum / local.secondNum;
}

显然,还有其他情况需要考虑,例如通过引用传递的复杂对象或结构,以及这些对象是否在函数中被修改。但希望这能阐明"保存数据"的含义,以及作用域如何区分状态组件(对application范围安全)和状态丰富组件(不是)。

TL;博士;

在您的情况下,听起来大多数信息都没有共享,并且是请求级别(用户信息、上传的图像等),因此存储在应用程序范围内可能是安全的。

最新更新