开发安全代码

Lightning Locker 架构层通过将单个 Lightning 组件命名空间隔离在自己的容器中并强制执行编码最佳实践来增强安全性。Lightning Web Security (LWS) 旨在使您的组件更容易使用安全编码实践,旨在取代 Lightning Locker。Lightning Locker 一直是 Lightning 组件的默认安全架构。LWS 最初在 22 年春季开始为 Lightning Web 组件替换 Lightning Locker。

Lightning 组件框架使用 JavaScript 严格模式在浏览器中打开本机安全功能。它使用内容安全策略 (CSP) 规则来控制可在页面上加载的内容源。

Lightning Locker 的安全性

Lightning Locker 提供组件隔离和安全性,允许来自多个来源的代码使用安全、标准的 API 和事件机制执行和交互。Lightning Locker 一直是 Lightning 组件的默认安全架构。Lightning Web Security (LWS) 旨在使您的组件更容易使用安全编码实践,旨在取代 Lightning Locker。LWS 最初在 22 年春季开始为 Lightning Web 组件替换 Lightning Locker。

JavaScript 严格模式强制执行

在 JavaScript 中,严格模式在模块中强制执行,但在常规程序中是可选的。但是,Lightning Locker 和 Lightning Web Security 隐式启用了 JavaScript 严格模式。无需在代码中指定。JavaScript 严格模式使代码更安全、更可靠、更受支持。"use strict"

当启用严格模式并采取不安全的操作时,JavaScript 会抛出错误,否则这些错误会被禁止。不安全操作的示例包括将值分配给不可写的属性以及使用尚未声明的变量。报告这些操作可以捕获变量名称键入错误的情况。

使用严格模式时的一些常见绊脚石是:

  • 您必须声明所有变量。使用库或模块中的任何 、 或声明。varletconst
  • 若要在组件之间共享代码,必须从模块中导出变量和函数,并将它们导入到其他模块中。请参阅共享 JavaScript 代码。
  • 组件使用的库也必须在严格模式下工作,但不需要在自己的代码中指定。请参阅使用第三方 JavaScript 库。"use strict"
  • 如果使用显式指定的第三方库,则可能会在 LWS 下出现错误。请参见使用 LWS 的第三方库严格模式。"use strict"

有关 JavaScript 严格模式的更多信息,请参阅 Mozilla 开发人员网络。

DOM 访问遏制

组件只能遍历 DOM 并访问它创建的元素。此行为可防止反模式进入其他组件拥有的 DOM 元素。

Lightning Web 组件不能使用 或 全局属性来查询 DOM 元素。例如,使用 而不是 .windowdocumentthis.template.querySelector()document.querySelector()

注意

使用 Lightning Web Security (LWS),组件对 DOM 的访问由浏览器通过 Shadow DOM 控制,Shadow DOM 是在 Web 浏览器中实现的 Web 标准。LWS 通过要求 to be 来强制关闭,这提供了额外的封装限制。参见 MDN 中的 ShadowRoot.mode。shadowRootmodeclosed

安全包装纸

为了安全起见,Lightning Locker 通过隐藏对象或将其包装在对象的安全版本中来限制全局对象的使用。例如,的安全版本是 。Locker 会截获对 的调用并改用。windowSecureWindowwindowSecureWindow

若要查看 、 和包装器支持哪些 API,请使用 Locker API 查看器工具。SecureWindowSecureDocumentSecureElementSecureWindow

可用:Lightning Web 组件和 Aura 组件

对象的安全包装器,它表示包含 DOM 文档的窗口。window

如果 Lightning Web 组件和 Aura 组件属于同一命名空间,则它们共享同一实例。SecureWindowSecureDocument

可用:Lightning Web 组件和 Aura 组件

对象的安全包装器,表示 HTML 文档或页面的根节点。对象是页面内容的入口点,即 DOM 树。documentdocument

如果 Lightning Web 组件和 Aura 组件属于同一命名空间,则它们共享同一实例。SecureDocumentSecureObject

可用:Lightning Web 组件和 Aura 组件

由 Lightning Locker 包装的对象的安全包装器。当您看到 时,这通常意味着您无权访问基础对象,并且其属性不可用。SecureObjectSecureElement

可用:Lightning Web 组件和 Aura 组件

对象的安全包装器,表示各种 HTML 元素。element

如果 Lightning Web 组件和 Aura 组件属于同一命名空间,则它们共享同一实例。SecureElement

Lightning Web 组件还使用包装器。SecureLightningElementSecureLightningElement

可用:Lightning Web 组件

基类的安全包装器。Lightning Web 组件扩展了基类,并在运行时 Locker 使用 .创建 Lightning Web 组件时,请勿直接扩展。LightningElementLightningElementSecureLightningElementSecureLightningElement

不支持这些 API。

  • Element.attachShadow()
  • Element.shadowRoot – 改用this.template
  • Element.slot

SecureTemplate

可用:Lightning Web 组件

对象的安全包装器,表示节点。templateshadowRoot

不支持这些 API。

  • Node.localName
  • Node.namespaceURI
  • Node.nodeValue
  • Node.nextSibling
  • Node.previousSibling
  • Node.parentElement
  • Node.parentNode
  • Node.prefix
  • NonDocumentTypeChildNode.nextElementSibling
  • NonDocumentTypeChildNode.previousElementSibling
  • DocumentOrShadowRoot.getSelection()
  • DocumentOrShadowRoot.styleSheets
  • DocumentOrShadowRoot.pointerLockElement
  • DocumentFragment.getElementById()
  • ParentNode.append
  • ParentNode.prepend
  • constructor
  • EventTarget.dispatchEvent
  • pictureInPictureElement

注意

Lightning Web Security 不使用包装器。它使用 JavaScript 沙盒中的 API 失真来有选择地修改启用非安全行为的 API。

eval() 函数受 Lightning Locker 限制

在 Lightning Locker 中,支持使用该函数来启用动态评估代码的第三方库。但是,它仅限于在命名空间的全局范围内工作。该函数无法访问调用它的范围内的局部变量。eval()eval()

通常,有两种执行模式。直接调用时,它在本地范围内工作。当您通过引用调用它时,它会在全局范围内工作。Lightning Locker仅支持后者。eval()eval()

例如,假设您执行以下代码:

window.foo = 1;
function bar() {
  var foo = 2;
  return eval("foo");
}

在本地范围内执行评估时,调用 2 时返回 2,在全局范围内执行评估时返回 1。如果必须使用本地范围中的变量,请重构代码。使用 ,将局部变量声明为参数,将它们作为参数传递,并添加 return 语句:bar()Function()

window.foo = 1;
function bar() {
  var foo = 2;
  return Function("foo", "return foo")(foo);
}

提示

Lightning Web Security 不限于全局范围,因为代码在沙盒中执行。但是,仍然不建议直接在本地范围内调用。eval()eval()

允许的 MIME 类型

Lightning Locker 分析 Blob 对象中使用的 MIME 类型。Locker 允许某些 MIME 类型,清理某些 MIME 类型,并阻止其余类型。

Lightning Locker 允许这些 MIME 类型。

  • application/octet-stream— 二进制文件的默认值
  • application/json— JSON 格式
  • application/pdf— 可移植文档格式 (.pdf)
  • video/— 所有哑剧类型video/*
  • audio/— 所有哑剧类型audio/*
  • image/— 所有哑剧类型image/*
  • font/— 所有哑剧类型font/*
  • text/plain— 文本 (.txt)
  • text/markdown— 降价 (.md)
  • application/zip— 压缩存档 (.zip)
  • application/x-bzip— Bzip 存档 (.bz)
  • application/x-rar-compressed— RAR 存档 (.rar)
  • application/x-tar— 磁带存档 (.tar)

Locker 清理 、 和 MIME 类型。这些类型是允许的,但 Locker 会删除潜在的恶意代码。text/htmlimage/svg+xmltext/xml

任何其他类型都会被阻止,并显示错误消息。Unsupported MIME type

若要发送未明确允许的二进制文件,请将 MIME 类型指定为 .application/octet-stream

提示

Lightning Web Security (LWS) 要求您指定 MIME 类型。请参阅在 LWS 中指定 Blob 对象的 MIME 类型。

带有 Lightning Locker 的第三方 Web 组件

Lightning Locker 阻止使用第三方 Web 组件,以防止 Salesforce 平台上的安全风险。

Web 组件是自定义元素。若要定义自定义元素,必须使用 API。但是,此 API 允许您按标记名称全局注册组件。全局注册标记名称存在安全风险,因为攻击者可以创建任何已注册自定义元素的实例,并可能获得对敏感信息的访问权限。Lightning Locker 的包装器阻止了创建自定义 Web 组件的方法。customElements.defineSecureWindowcustomElements

Locker API 查看器工具中的包装器列表显示不受支持。SecureWindowcustomElements

对 Salesforce 全局变量的访问受限

Lightning Locker 阻止访问其他 Salesforce 功能可用的某些全局 JavaScript 对象。

Lightning Web 组件无权访问

  • $A
  • Aura
  • Sfdc
  • sforce

Locker 限制了 Lightning Web 组件对这些对象的访问,因为它们要么已被弃用,要么会导致跨框架依赖。

Lightning Locker为不受支持的浏览器禁用

Lightning Locker 依赖于浏览器中的一些 JavaScript 功能:支持严格模式、对象和对象。如果浏览器不符合要求,Lightning Locker 将无法强制执行其所有安全功能,因此会被禁用。WeakMapProxy

Lightning Locker 在 Lightning Experience 支持的浏览器中启用。如果您的应用在不受支持的浏览器中运行,您可能会遇到无法修复的问题。通过要求应用在受支持的浏览器中运行,使你的生活更轻松,用户的浏览体验更安全。

注意

IE11 禁用了 Lightning Locker。对 IE11 的支持将于 2022 年 12 月 31 日结束。

传递给子组件时代理的数组

当您将数组传递给子组件时,Lightning Locker 会将该数组包装在代理中。

JavaScript 用于传递给嵌套组件的数组。如果将数组从父组件传递到嵌套组件的多个层,则会多次代理该数组。当数组由多个对象组成时,多个代理在运行函数(例如在数组上)时会对性能造成负面影响。如果页面使用的组件通过子组件层传递大量对象,则该组件可能会变得无响应。ProxyJSON.stringify

若要限制处理大型数组对性能的负面影响,请使用以下方法之一重构代码。

  • 避免将大型对象数组向下传递多个级别。例如,将数组从父级传递到子级,但不要进一步传递。
  • 在父组件中将数据划分为多个较小的数组。

Lightning Web Security (LWS) 没有此限制。

使用 Lightning Locker 运行的 querySelector API

启用 Lightning Locker 后,使用或 API 返回元素的组件可能会遇到大型 DOM 树的内存泄漏和性能问题。从 DOM 中删除组件时,内存有时不会释放。即使在 DevTools 中手动调用垃圾回收,垃圾回收也不会清除内存。浏览器可能会使用不断增加的内存量,并可能因内存不足错误而崩溃。this.template.querySelectorthis.template.querySelectorAll

此问题的唯一解决方法是在运行组件的组织中启用 Lightning Web Security。垃圾回收在 LWS 下正常工作。

或者,考虑使用 refs 而不是 .querySelector

Lightning Locker工具

Lightning Locker 工具可帮助您开发与 Lightning Locker 兼容并高效运行的安全代码。Lightning Locker API 查看器

使用 Lightning Locker API 查看器查看 Lightning Locker 支持哪些标准 DOM API 用于最复杂的包装器:、 和 。SecureDocumentSecureElementSecureWindow

储物柜控制台

使用 Locker 控制台检查 JavaScript 代码与 Lightning Locker 的兼容性,并比较它在启用和禁用 Lightning Locker 时的运行方式。

评估 JavaScript 代码是否存在问题或基准测试代码,而无需创建应用。

要评估或基准测试您的 JavaScript 代码,请将其粘贴或键入到控制台中 (1)。启用或禁用 Locker 和 Strict CSP (2)。若要运行控制台中显示的代码,请单击“评估”(3)。若要使用和不使用 Locker 运行代码并查看相关性能指标,请单击“基准测试”。要清除显示的结果,请单击“清除结果”。

选择组织的 Locker API 版本

选择 Lightning Locker 在整个组织中使用的 API 版本。默认值为当前 API 版本,其中包括最新的 Locker 安全增强功能。当自定义组件仅符合旧版本中的 Locker 时,请选择较早的 API 版本。当组件符合当前安全增强功能时,您可以将设置更改为当前 API 版本。

在您的沙盒组织更新到新的 Salesforce 版本后,自定义组件可能会与 Lightning Locker 安全增强功能发生冲突。检查 Web 控制台中是否有消息。

我们建议更新自定义组件以符合最新的 Locker API 版本,但我们知道更新可能需要一些时间。您的组织还可能依赖于包含第三方开发人员必须更新的自定义组件的托管包。将您的组织设置为使用较旧的 Locker API 版本,以便开发人员有时间更新自定义 Lightning 组件并遵守 Locker 的最新安全增强功能。

在沙盒组织中验证自定义组件是否在将 Locker API 版本设置为最新版本的情况下正确执行。然后,可以将 Locker API 版本更改为生产组织中的最新版本,以利用最新的安全增强功能。

注意

Locker API 版本设置在 Winter ’20 版本中首次提供。您可以选择的最早 Locker API 版本是 46.0,它启用了 Summer ’19 版本的 Locker 功能。

使用更衣室 API 版本的位置

组织的 Locker API 版本会影响 Lightning Locker 影响什么?中列出的区域中使用的所有 Lightning 组件。

在组织中启用 Lightning Web Security 时,组织的 Locker API 版本对 Lightning Web 组件没有影响。

注意

每个 Lightning Web 组件都有一个配置文件,其中包含 .组件和 Locker API 版本使用相同的版本号策略来与 Salesforce 版本保持一致。但是,Locker API 版本的组织设置与组件的 .组织中设置的 Locker API 版本适用于所有 Lightning 组件,无论其设置如何。apiVersionapiVersionapiVersionapiVersion

Locker API 版本更改

查看 API 版本中的安全更改,以帮助确定自定义组件的兼容性。

Locker API 版本安全更改描述
53.0 及更高版本没有此版本中的 Lightning Locker 更改不会影响自定义组件。
52.0防止多个潜在的基于突变的跨站点脚本 (mXSS) 向量。Lightning Locker 加强了标记的清理以提高安全性。此更改适用于所有 API 版本。无法通过选择较早的 API 版本来回滚此更改。
51.0没有此版本中的 Lightning Locker 更改不会影响自定义组件。
50.0没有此版本中的 Lightning Locker 更改不会影响自定义组件。
49.0限制 API$A.getCallback()Lightning Locker 包装该功能。包装的 JavaScript 必须遵守 Locker 的安全限制。请参阅 Locker API 查看器,了解 Lightning Locker 中 JavaScript API 的支持状态。$A.getCallback()$A.getCallback()
48.0清理插入的 HTMLexecCommandLightning Locker 会清理插入的 HTML,用于删除潜在的恶意可执行脚本内容。document.execCommand(insertHTML)
47.0拒绝表达式import()Lightning Locker 不允许该表达式,因为导入第三方代码存在潜在的安全风险。import()
 限制 HTML 元素的 和 属性nameidLightning Locker 不允许将 or 属性设置为为 DOM 保留的属性名称。nameid
46.0所有 Locker 安全功能支持自 Lightning Locker 推出以来的所有功能,当时它被称为 LockerService。这包括版本 37.0(16 年春季)到版本 46.0(19 年夏季)版本中的所有功能。

更改组织的 Locker API 版本

  1. 在“设置”中,输入“快速查找”框,然后选择“会话设置”。Session
  2. 在“Locker API 版本”部分中,对于“在 API 版本中使用安全增强功能”字段,选择 API 版本。
  3. 点击保存