创建安全 ThingWorx 小组件
创建自定义小组件时,请确保创建安全小组件。您必须考虑跨站点脚本 (XSS) 和跨站点请求伪造 (CSRF) 漏洞。有关详细信息,请参阅 更新 CSRF 保护的请求方法和内容类型筛选部分。
以下各部分提供了创建安全小组件的最佳做法。
将编码用于小组件中的 HTML 输出值
如果使用小组件在用户界面中显示值,则建议使用 HTML 编码。请参阅以下示例代码:
this.updateProperty = function (updatePropertyInfo) {
if (updatePropertyInfo.TargetProperty === 'Text') {
var labelText = Encoder.htmlEncode(updatePropertyInfo.SinglePropertyValue);
thisWidget.setProperty('Text', labelText);
showLabelText(thisWidget.getProperty('Text'));
}
}
在本示例中:
每次小组件属性的绑定值发生变化时都会调用函数 updatePropery()
小组件中的值是使用编码器库进行 HTML 编码的。
编码后,使用 Get 和 Set 方法访问此新值。
此步骤可确保 Get 方法对返回到用户界面的值执行额外的清理操作。
将解码和 jQuery 用于小组件中的 HTML 输出值
如果使用小组件在用户界面中显示值,并已使用 HTML 编码对值进行编码,请使用 HTML 解码将已编码的值转换为其原始值。请参阅以下示例代码:
function showLabelText(labelText) {
labelText = Encoder.htmlDecode(labelText);
var spanText = thisWidget.jqElement.find('.label-text');
spanText.text(labelText);
}
在本示例中:
函数 showLabelText 用于获取小组件的 DOM 元素并更新值。
使用编码器库对值进行解码。
对 DOM 元素使用 jQuerytext() 方法来显示值。此方法具有内置转义函数,有助于保护应用程序免受 XSS 漏洞的影响。
将编码用于 JavaServer Pages (JSP) 中的 HTML 输出值
如果使用 JSP 在用户界面中显示值,则建议使用 HTML 编码。您可以使用 OWASP 中的 ESAPI 实用程序来根据上下文处理编码。请参阅以下示例代码:
<div class="org-info">
<h1 class="orgName">
<%=ESAPIUtilities.getEncoder().encodeForHTML(orgName)%>
</h1>
<p class="orgDescription"><%=ESAPIUtilities.getEncoder().encodeForHTML(loginPrompt)%></p>
</div>
在本示例中:
用户可以为 ThingWorx 创建自己的登录页面。
以下字段需要登录屏幕的用户输入:
orgName
loginPrompt
这些字段中的数据是不受信任的数据。用户可能会输入这些字段的恶意字符,由此构成潜在威胁。因此,需要通过 ESAPI 实用程序来运行此数据,以实现 HTML 编码。
安全的自定义用户界面
您可以通过开发扩展来构建您自己的自定义用户界面,或者拥有您自己的托管 Web 应用程序,且这些应用程序使用的是 ThingWorx REST API。在这些情况下,应确保先对数据进行清理和编码,然后再将其显示在浏览器中。
请确保您了解您要实现的框架,并针对此环境采取最佳做法来保护应用程序免受 XSS 漏洞的影响。
在以下示例中,AngularJS 应用程序使用的是已导入为扩展的模板。您可以使用 ThingWorx 实用程序来构建此工作流。
<div class="node-label-wrap" ng-class="{'graph-node-nonadmin': $parent.$parent.isNonAdminUser}">
<textarea type="text" ng-model="node.label" ng-change="$parent.$parent.setBPUpdatesMade()">
</textarea>
<div class="node-label">{{node.label}}</div>
</div>
在本示例中:
node.label 为不受信任的用户输入。这是一个任意字符串。由用户提供工作流节点的标签名称。
在 AngularJS 应用程序的模板中,如果用双大括号表示法 {{}} 括起不受信任的输入,例如 {{node.label}},它会强制执行字符串插值。该值将被视为字符串,而不会在脚本的上下文中执行。
HTML 响应
PTC 将其 HTML 响应记录在通过 ESAPI 实用程序筛选任何输出的公共类中。
public void writeTableCell(String value, String id, String sClass, String sStyle) throws Exception {
startTableCell(id, sClass, sStyle);
writeValue(value);
endTableCell();
}

public void writeValue(String value) throws Exception {
write(ESAPIUtilities.getEncoder().encodeForHTML(value));
}