在应用程序范围内存储CFC用户内容处理程序是否安全?

时间:2019-06-02 15:39:53

标签: coldfusion coldfusion-2018

我已经阅读了很多有关在应用程序范围内存储CFC的帖子,并且我知道,如果CFC存储数据,那么它就不应该在应用程序范围内。所有执行非实用程序功能的CFC都会存储数据-当您传递诸如用户名或电子邮件地址之类的参数时-这样我就不会知道何时以及何时不将应用程序范围用于非实用程序cfc。

我的问题是,我有一个约500行代码的posthandler.cfc组件,该组件可以处理来自用户的帖子(就像SO可以处理在此站点上发布的每个问题一样)。 posthandler.cfc组件:

  • “清除”用户提交的所有图像和文字
  • 将图像放置在正确的文件夹中
  • 将所有文本写入数据库
  • 返回一个可以在其中查看帖子的URL

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

这种情况在网站上经常发生,此刻正在为每个帖子创建一个新的CFC实例。将其放到应用程序范围内并且不会引起争用/锁定情况,是否安全?

1 个答案:

答案 0 :(得分:2)

仅传递参数不会“保存”任何内容。从概念上讲,每个线程都有自己的argumentslocal范围,这对任何其他线程都不可见,并且在函数退出时不再存在。因此,从这个角度来看,没有冲突。

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

例如,使用这个(人为设计的)组件函数在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 pointed out一样,省略范围时也会发生相同的问题。 声明没有作用域的函数变量不会使它成为函数的局部变量。它使其成为默认范围的一部分: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;
 }

很明显,还有其他情况需要考虑,例如通过引用传递的复杂对象或结构,以及这些对象是否在函数中被修改。但是希望这可以阐明“保存数据”的含义以及范围界定如何使状态 less 组件(对于application范围是安全的)和状态 ful 组件(不是)。

TL; DR;

对于您来说,听起来大多数信息都没有共享,并且是请求级别的(用户信息,上载的图像等),因此可以安全地存储在应用程序范围内。