背景
近期工作中有一个前端弹窗在关闭时,没有及时清空表单字段引发了一段思考;
设想一下,如果对应的数据没有被清除,数据会一直存储在内存中。长期下来是否会造成内存泄漏?
又或者如果将一些敏感信息如密码存储在内存中,是否会被dump偷走?
先说结论,在以前端的思维来看,大部分场景都是用空间换时间/体验,即在组件的生命周期内,一般不主动清除数据,而是随着生命周期结束自动清理。
另外前端安全的核心在于 防止恶意代码执行(CSP、防 XSS) 和 防止网络层窃听(HTTPS),不在于通过缩短变量在内存中的存活时间来防御。
数据清除时机的最佳实践
在弹窗关闭的时候就去清除数据,虽然直觉上觉得“用完即走,关掉就清理”很符合逻辑,但在我们的cc工程中,它存在两个明显的痛点:
视觉体验会有闪烁
目前的弹窗组件( Ant Design Vue)在关闭时有过渡动画。那么在此时调用
form.resetFields()来清空表单数据,会出现数据瞬间闪白被清空(原理是触发了rerender,动画重新执行),然后再关闭弹窗,视觉体验会很差。代码健壮性:
从代码层考虑,关闭弹窗的事件/入口有非常多,用户可以通过多种方式关闭弹窗,需要在这些场景都做兼容处理:
- 点击“取消”按钮。
- 点击右上角的“X”图标。
- 键盘esc
- 提交成功后自动关闭
- 强制刷新浏览器
- 电脑死机……
而我们打开弹窗永远只有一个入口,就是某一个比如新增,或者编辑的按钮。
因此从代码可维护性和健壮性来考虑,在打开弹窗的时候去做初始化弹窗/清空状态是更加合适的。
内存泄漏
首先内存泄漏一定是无法被回收的变量导致的。那么在我们的前端表单数据中,它是依附于一个组件之上的。每个组件都有自己的生命周期,当路由切换、这个组件被销毁。这个组件的所有变量都会被浏览器彻底回收。
而内存泄漏的真凶应该是一些挂载到全局window的变量、一些没有清除的定时器、一些三方库创建的实例没有及时清除。这里我们先不展开了。
另外,由于前端的环境是**“一对一”**(一个浏览器只服务一个用户),且运行在用户的终端设备上。所以前端对于内存是比较开放的,只要不是存了几万条列表数据,或者存了 Base64 的高清大图,完全不会有内存泄漏导致崩溃的风险。
前端安全
首先在前端安全模型中,数据的生命周期长短与数据安全性几乎不挂钩。如果攻击者能够读取用户浏览器的内存堆栈,说明用户的设备环境已经彻底沦陷(如中了木马、操作系统被攻破),此时清空敏感变量也没有任何意义
换句话说,如果黑客能 Dump 内存,意味着他已经拥有了该设备的最高权限。他完全可以在用户输入密码的瞬间通过记录键盘操作获取,而不需要去内存里找残留。
而前端最大的威胁其实是跨站脚本攻击(XSS)。如果网站存在漏洞,恶意脚本会在用户输入时直接劫持数据。无论后续是否清空变量,数据在输入的瞬间就已经泄露。
真正的安全防线:
前端安全的核心在于 防止恶意代码执行(CSP、防 XSS) 和 防止网络层窃听(HTTPS)
XSS (Cross-Site Scripting):
XSS 攻击的核心是:黑客把一段恶意的 JavaScript 代码“注入”到了你的网页里,让浏览器误以为这是你写的代码,然后执行了它。
CSP (Content Security Policy):
CSP 是浏览器的一种安全机制,用于拦截浏览器执行白名单以外的js脚本
原理: 在 HTTP 响应头里加一行规则(Whitelist):
Content-Security-Policy: script-src 'self' https://apis.google.com效果:
浏览器在加载html后,当解析js文件的时候,只有来自我的域名**(’self’)和 **Google API 的 JS 文件可以运行。
防止网络层窃听
这里主要就是使用https,将通过网络传输的内容进行加密,这样别人抓包到你的数据后,由于没有私钥,也没有什么用
其实还有一些网站安全的攻击手段,如CSRF、DDoS,虽然它们不直接和前端有关系,但是前端也可能成为帮凶;我们可以在后续聊到这一个话题