【问题标题】:CFIncludes best-practice and potential security concernsCF 包括最佳实践和潜在的安全问题
【发布时间】:2014-01-14 04:48:56
【问题描述】:

我正在编写一个应用程序,其中包含许多对话框/模态 div,允许用户执行各种任务,例如上传图片、发送电子邮件等

我的应用程序具有基于角色的安全性,因此当您登录时,它会检查您的会话变量以找出您的身份,然后提供相应的功能。

目前我的所有对话框/模式都在需要它们的页面中。这意味着如果我想在我网站的其他地方使用相同的对话框,我必须复制代码并将其放在该页面上。这立刻让我觉得我应该:

  1. 为每个对话框创建一个 .cfm 文件,例如imageupload.cfmemailsend.cfm
  2. 使用<cfinclude> 将这些 .cfm 文件包含在任何想要使用它们的页面上

这个潜在的解决方案给我带来了挑战,因为包含对话框的页面有许多 if/else 语句,可以根据用户的角色(存储在会话变量中)确定向哪个用户呈现什么。

我必须这样做:

  1. 也将 if/else 逻辑语句复制到对话框页面,因为 例如,imageupload.cfm 提供的内容会因您的角色而异
  2. 站点中的每个页面都受到调用user-security.cfc 文件的保护,该文件检查用户是否已登录。我是否还必须在每个对话框.cfm 页面中进行此调用?如果我这样做,那么在同一页面内将有两次调用同一 user-security.cfc 文件,因为对话框页面包含在主页中。但是,如果我也不从对话框 .cfm 中调用user-security.cfc,那么有人会直接进入这些页面并开始造成混乱吗?

很抱歉,这不是一个纯粹的编程问题和更多理论上的最佳实践,但我不确定如何在保持可扩展性的同时解决它。我在 IIS 7.5 上使用 ColdFusion 10

【问题讨论】:

  • 您从哪里调用 user-security.cfc?
  • 怀疑您应该阅读 MVC 原则并查看已经存在的框架(FW/1、Coldbox 等),因为在我看来您是可能在这里重新发明轮子。
  • 我认为这是一种特别糟糕的方法,显示出判断力差,只会为自己做不必要的工作。并且 - 鉴于您似乎是这方面的新手 - 将导致不太理想的解决方案。仍然:您的电话。只能把马牵到水边。
  • 不使用框架,因为你不知道它是如何工作的,就像拒绝开车,因为你不知道内燃机是如何工作的。框架解决了每个 Web 应用程序都会遇到的问题。不要重新发明轮子。
  • 我会大胆猜测,由框架作者编写并由数百名开发人员使用和测试的代码会比您组装的“本土”框架更值得信赖。

标签: security coldfusion coldfusion-10


【解决方案1】:

您可以通过以下方式提高代码的可重用性。

使用您的 user-security.cfc 文件的实例创建一个应用程序范围变量。在 Application.cfc 文件的 onApplicationStart() 方法中执行此操作。像这样的:

application.SecurityChecker = CreateObject("component", "user-security");

同样在您的 onApplicationStart() 方法中,创建一个不需要安全检查的页面列表。

application.SecurityNotNeededPages="page1.cfm,page2.cfm,etc";

在你的 onRequestStart() 方法中使用这些变量。

var ThisPage = listlast(cgi.PATH_INFO, "/");
if (ListFindNoCase(application.SecurityNotNeededPages, ThisPage) is false) {
application.SecurityChecker.CheckSecurityMethod(argumentcollection = session);
etc

这将解决人们在未登录的情况下直接浏览包含页面的问题。它还将使您的应用程序运行得更快,因为您只需创建一次 user-security.cfc 的实例,它会对每个页面请求的每个用户都可用。

编辑从这里开始

在 cmets 中,Adam Cameron 说:“另外,onRequestStart() 已经接收到被请求文件的名称作为参数;我认为不需要使用 CGI 范围来获取它”。这对我来说是个新闻,所以我想我会去看看。

我运行了一个具有此功能的页面。

<cffunction name="onRequestStart" access="public" returntype="boolean">
<cfdump var="#arguments#">
<cfreturn true>
</cffunction>

这给了我一个 1 的键,以及显示我实际运行的页面的路径的值。所以,按错误的顺序做事,我读了the docs。按照这些准则,我将其添加到上面的代码中:

<cfargument name="targetPage" required="yes">

毫不奇怪,转储给出了具有相同值的 TARGETPAGE 键。然后我将参数的名称更改为“fred”。转储给了我一个具有相同值的 FRED 键。

底线是,无论您使用发送到页面的参数还是 cgi 范围,您仍然必须使用 ListLast 来获取页面的名称。

【讨论】:

  • “包含”文件首先不应位于可浏览网页的目录中。只有打算浏览的文件才应该在网站目录中。 一般这只会是 index.cfm。此外,onRequestStart() 已经接收到被请求文件的名称作为参数;我认为没有必要使用 CGI 范围来获取它。
  • 感谢 Dan 非常有用。请问为什么要创建用户安全组件的对象而不是在onRequestStart() 函数中调用它?
  • 因为一个函数应该做一件事 if poss。 onRequestStart() 应该准备好请求环境,这可能涉及调用安全检查代码,但它实际上不应包含安全检查代码。
  • 谢谢亚当。我发现如果您尝试从 onRequestStart() 函数中调用,它会在 IE 中失败(在 Firefox 中有效)。使用 createObject 方法,它在 IE 和 Firefox 中运行良好。
  • @DanBracuk... 你是这里唯一提到&lt;cfinvoke&gt; 的人。你指的是什么?而且,错误...一个可以使用&lt;cfinvoke&gt;重用现有对象。 component 属性将采用对象引用以及 CFC 引用。
【解决方案2】:

创建一个 index.cfm 页面,该页面基本上由一个大的 switch 语句组成。您的 URL 是 action.subaction,即 index.cfm?action=email.send。在 index.cfm 中解析它。然后对于每种情况,根据需要检查安全规则和 cfinclude。但是,是的,您确实需要学习一个框架。 FW/1 会做你想做的事,而且很容易学习。我相信 Coldbox 也有极简版本。

【讨论】:

    【解决方案3】:

    &lt;cfinclude&gt; 将适用于任何具有任何扩展名的文件。作为标准做法,我将所有包含的内容命名为 *.cfi

    在 FW/1 世界中,这特别有用。

    我可以有目录

    views/reports/home.cfm
    views/reports/details.cfm
    views/reports/header.cfi
    

    有效链接包括

    index.cfm/reports/home
    index.cfm/reports/details
    

    但是

    index.cfm/reports/header
    

    什么都不做

    这样做是为了向其他开发人员传达我打算让文件做什么。

    【讨论】:

    • 您的包含 .cfi 文件是否包含任何 if/else 逻辑,以便它们为正确的用户角色提供适当的标头信息?例如,假设管理员在其标题中需要服务器信息,但销售人员只想查看当前日期时间。您将如何确保它有效?
    • 那些条件标题应该由单独的文件处理。您应该有一个用于 [the stuff] 的视图文件,以及用于 [header] 和 [footer] 文件的其他视图文件。说真的……通过阅读 MVC 并仅 使用框架,您对所有东西如何工作的理解程度会大大得到改善。比起像现在这样徘徊不定,你会从中得到更多。
    • @JamesMohler... 为什么要使用非标准文件扩展名?如果你提倡这个建议(我认为你不应该这样做),你还应该确保你特别提倡永远不要将这些文件放在网络可浏览的目录中,或者让网络服务器知道确定 i>不 提供 .CFI 文件。否则,一个人可能会浏览到您的 .cfi 文件,并查看您的所有源代码。这是一个等待发生的安全漏洞。
    • 听起来像是“没有时间把事情做好,但总有时间做两次”
    • 问题是......使用框架很容易。写一个很难。不要重新发明轮子。使用轮子。让轮子运转起来。这是学习这些东西如何工作的研究的一部分!想想学校:你不是靠编造的东西来学习的,你是通过跟随专家的榜样来学习的。不要以为你会通过尝试编写自己的框架或尝试不使用框架来学习任何有用的东西。这是错误的做法。这是十多年的经验。
    猜你喜欢
    • 2011-04-08
    • 2010-09-28
    • 1970-01-01
    • 2011-01-26
    • 2013-06-19
    • 2014-01-17
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多