Ember 2.18.0中能否重写Ember.set() API检测原型污染?
在Ember 2.18.0中避免Ember.set原型污染的替代方案
由于无法直接重写Ember.set API,可通过以下几种可行方案实现危险参数的检查:
1. 封装安全版Set工具函数
创建一个全局的安全设置函数,替代所有直接调用Ember.set的场景,在函数内部先完成不安全key的校验,再调用原生Ember.set:
// app/utils/safe-set.js export default function safeSet(obj, key, value) { // 定义禁止设置的危险key列表 const unsafeKeys = ['__proto__', 'constructor', 'prototype']; if (unsafeKeys.includes(key)) { // 根据业务需求选择:抛出错误/忽略操作/打日志 throw new Error(`禁止设置危险属性:${key}`); } return Ember.set(obj, key, value); }
使用时直接导入并替换Ember.set:
import safeSet from 'app/utils/safe-set'; // 替代 Ember.set(obj, 'someKey', value) safeSet(obj, 'someKey', value);
注意:需要梳理项目中所有Ember.set的调用点,逐步替换,适合长期迭代优化。
2. 全局覆盖Ember.set(谨慎使用)
如果项目允许修改全局Ember对象的方法引用,可以在应用初始化阶段覆盖Ember.set,注入校验逻辑:
// app/initializers/safe-set.js export function initialize() { const originalSet = Ember.set; Ember.set = function(obj, key, value) { const unsafeKeys = ['__proto__', 'constructor', 'prototype']; if (unsafeKeys.includes(key)) { console.warn(`拦截危险属性设置:${key}`); // 可选:直接返回,不执行设置操作 return obj; } return originalSet(obj, key, value); }; } export default { name: 'safe-set', initialize };
注意:这种方式会影响所有调用Ember.set的代码,需充分测试原有功能是否受影响,避免破坏Ember内部的属性处理逻辑。
3. 用Proxy包装目标对象
利用ES6 Proxy拦截对象的属性设置操作,即使通过Ember.set赋值也会经过校验:
// app/utils/safe-proxy.js export default function createSafeProxy(obj) { return new Proxy(obj, { set(target, prop, value) { const unsafeKeys = ['__proto__', 'constructor', 'prototype']; if (unsafeKeys.includes(String(prop))) { throw new Error(`尝试设置不安全属性:${prop}`); } // 调用Ember.set确保符合Ember的属性系统规则 Ember.set(target, prop, value); return true; } }); }
使用时将需要保护的对象用Proxy包裹:
import createSafeProxy from 'app/utils/safe-proxy'; const myObj = createSafeProxy(Ember.Object.create()); Ember.set(myObj, 'normalKey', 'value'); // 正常执行 Ember.set(myObj, '__proto__', {}); // 抛出错误
注意:Ember 2.18兼容ES6 Proxy(需确保目标浏览器支持),但Proxy可能会干扰Ember内部的元数据追踪,建议仅在特定敏感对象上使用。
4. 为Ember对象添加Mixin扩展
创建一个包含安全设置方法的Mixin,让需要保护的类混入该Mixin,通过实例方法而非全局Ember.set操作属性:
// app/mixins/safe-set.js export default Ember.Mixin.create({ safeSet(key, value) { const unsafeKeys = ['__proto__', 'constructor', 'prototype']; if (unsafeKeys.includes(key)) { console.error(`非法属性设置:${key}`); return; } this.set(key, value); // 调用Ember对象的实例set方法 } });
在类中使用Mixin:
import Ember from 'ember'; import SafeSetMixin from 'app/mixins/safe-set'; export default Ember.Component.extend(SafeSetMixin, { someAction() { // 替代 this.set('key', value) this.safeSet('key', value); } });
注意:仅适用于Ember.Object的子类(组件、控制器、模型等),无法覆盖全局Ember.set的调用。
内容的提问来源于stack exchange,提问作者Blg
相关产品推荐
相关产品推荐

