Salesforce 从 Winter'17 版本开始在 Lightning 框架中引入了 Locker Service 机制。
Locker Service 机制的引入可以增强 Lightning 应用的安全性。
Locker Service 的作用
Lightning 的应用本质上是 JavaScript 应用,其中包含了由各种 HTML 页面元素组成的“文档对象模型树”(DOM Tree,参考官方定义)。
与此同时,Lightning 应用是组件化的,来自不同开发者的组件可以以 DOM 的形式存在于同一个应用页面中。如果没有任何的防护措施,这些 DOM 是可以互相访问的,从而带来安全隐患。
在 Lightning 框架中,不同来源的组件是由命名空间(namespace)来确定的,比如标准的组件有 “ui:button”、“lightning:select” 等,它们就属于不同的命名空间。
Locker Service 的主要作用就是提供了虚拟的 DOM 元素,将不同命名空间的组件封装起来,限制它们之间的访问。
封装组件
Locker Service 中预定义了一些安全组件,将实际的 DOM 封装起来,比如:
- SecureComponent:将同一命名空间下的 Component 元素封装起来
- SecureComponentRef:另一命名空间下的 Component 元素
- SecureWindow:将 window 元素封装起来
- SecureDocument:将 document 元素封装起来
代码示例
我们通过一段代码来看看实际应用的情况。
Lightning 组件:
<aura:component >
<!-- 定义一个 div 元素 -->
<div id="idDiv" aura:id="idDiv">
<p>Hello World!</p>
</div>
<!-- 定义一个 lightning 命名空间下的 button 元素 -->
<lightning:button name="button" label="click here" aura:id="idButton" onclick="{!c.handleClick}" />
</aura:component>
相应的控制器代码:
({
handleClick : function(component, event, helper) {
debugger;
},
})
在用户点击按钮之后,JavaScript 的 debugger 语句可以让我们在控制台中进行断点调试。
现在我们执行一些命令:
命令:
window+''
结果:
"SecureWindow: [object Window]{ key: {"namespace":"c"} }"
解释:
我们想要显示 window 元素,可以看到结果中给出的是 SecureWindow 元素,也就是说原始的 window 元素已经被封装起来了。
命令:
component.find('idDiv')+''
结果:
"SecureComponent: markup://aura:html {5:0} {idDiv}{ key: {"namespace":"c"} }"
解释:
我们想要显示 div 元素,结果可以看到它已经被封装到了 SecureComponent 元素中,其命名空间是 “c”,这是基本 HTML 元素的默认命名空间。
命令:
component.find('idButton')+''
结果:
"SecureComponentRef: markup://lightning:button {8:0} {idButton}{ key: {"namespace":"c"} }"
解释:
我们想要显示 lightning:button 元素,结果可以看到它已经被封装到了 SecureComponentRef 元素中,其命名空间是 “c”。lightning:button 元素本身的命名空间是 “lightning”,但是现在它被引用到了命名空间是 “c” 的组件中,所以类型是 SecureComponentRef。
命令:
component.find('idButton').getElement()+''
结果:
Uncaught TypeError: component.find(...).getElement is not a function
解释:
我们想要显示 lightning:button 元素中的内容,结果出错了,原因就是它属于命名空间 “lightning”,而我们所处的组件是属于命名空间 “c”,Locker Service 限制了它们之间的访问。