严格Setter需结合Object.defineProperty或Proxy与严格模式,仅允许预设权限键名及合法值域,拦截非法字符、越权字段和原型污染,并配合Object.seal、CSP等实现纵深防御。

严格 Setter 本身不是标准 JavaScript 特性,但结合 Object.defineProperty 或 Proxy + 严格模式("use strict"),可以构建出对用户权限字段写入行为的精准拦截机制——关键不在“禁止所有赋值”,而在于**只允许预设的、语义明确的权限键名和值域范围**,从源头切断非法字符、越权字段、原型污染等注入路径。
用 defineProperty 实现白名单式权限 Setter
对核心权限对象的每个属性显式定义 setter,拒绝非预期键名或非法值:
示例:仅允许 canRead/canEdit/maxRetries 三个字段,且值必须为布尔或数字
"use strict";
const userPerm = {};
Object.defineProperty(userPerm, "canRead", {
set(value) {
if (typeof value !== "boolean") throw new TypeError("canRead must be boolean");
this._canRead = value;
},
get() { return this._canRead; }
});
Object.defineProperty(userPerm, "canEdit", {
set(value) {
if (typeof value !== "boolean") throw new TypeError("canEdit must be boolean");
this._canEdit = value;
},
get() { return this._canEdit; }
});
// 其他字段同理...
// ❌ 以下全部失败:
// userPerm.isAdmin = true; // TypeError: can't define property "isAdmin"
// userPerm.canRead = "yes"; // TypeError: canRead must be boolean
// userPerm.maxRetries = -1; // 若 setter 中校验了 >= 0,则报错
用 Proxy 拦截所有赋值并统一校验
比 defineProperty 更灵活,适合动态权限结构,能一次性管控整个对象的写入行为:
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
立即学习“前端免费学习笔记(深入)”;
示例:只放行已知权限键 + 值类型/范围校验
"use strict";
const ALLOWED_KEYS = ["canRead", "canEdit", "maxRetries", "timeout"];
const PERMISSION_SCHEMA = {
canRead: { type: "boolean" },
canEdit: { type: "boolean" },
maxRetries: { type: "number", min: 0, max: 10 },
timeout: { type: "number", min: 100, max: 30000 }
};
const safePerm = new Proxy({}, {
set(target, key, value) {
if (!ALLOWED_KEYS.includes(key)) {
throw new TypeError(`Permission key "${key}" is not allowed`);
}
const schema = PERMISSION_SCHEMA[key];
if (schema.type === "boolean" && typeof value !== "boolean") {
throw new TypeError(`${key} must be boolean`);
}
if (schema.type === "number") {
if (typeof value !== "number" || value < schema.min || value > schema.max) {
throw new TypeError(`${key} must be number between ${schema.min} and ${schema.max}`);
}
}
target[key] = value;
return true;
}
});
防御非法字符与原型污染的关键细节
权限字段常被用于拼接 DOM、生成 API 路径或参与模板渲染,含非法字符(如 <、script、__proto__)会引发 XSS 或原型链篡改:
- 在 setter 或 Proxy 的
set钩子中,对字符串类权限值(如role)做基础过滤:value.replace(/['"/;{}=]/g, "") - 绝对禁止直接赋值
__proto__、constructor、prototype等敏感键名,可在 Proxy 中硬性拦截:if (key === "__proto__" || key === "constructor") throw new Error("Forbidden key") - 若权限对象需嵌套(如
{ api: { timeout: 5000 } }),Proxy 必须递归包装子对象,否则深层结构仍可被绕过
与 Object.seal() 和 CSP 协同加固
Setter 是第一道防线,但需配合其他机制形成纵深防御:
- 在初始化完成后调用
Object.seal(safePerm),防止后续新增字段或删除已有字段(注意:seal 不影响 setter 内部逻辑,但能堵住绕过 setter 的直接赋值) - 前端渲染权限相关 UI 时,禁用
v-html/dangerouslySetInnerHTML;必须富文本时,后端清洗 + 前端 CSPdefault-src 'self'限制脚本加载 - 权限数据不存于
window或localStorage,避免 XSS 后直接读取;优先使用内存对象 + 作用域封闭

















