Proxy 是 JavaScript 中实现细粒度对象访问控制最直接、最灵活的机制,通过 get/set 拦截敏感属性读写,结合用户角色动态判断权限,并组合 has、ownKeys、deleteProperty、apply 等 trap 统一拦截多种操作,同时需避免绕过陷阱如继承链失效、set 返回值错误及非递归代理问题。
proxy 是 javascript 中实现细粒度对象访问控制最直接、最灵活的机制。它不修改原对象,而是通过拦截操作,在读取、写入、枚举等关键环节插入权限逻辑,天然适合作为安全访问层。
用 get/set 拦截敏感属性读写
这是权限控制最常用的方式。比如禁止访问 password、token 等字段,或限制只读字段被意外修改:
- 在 get 中检查属性名,匹配敏感字段时返回
undefined或抛出错误 - 在 set 中校验赋值内容(如密码长度)、目标属性是否允许写入
- 推荐使用
Reflect.get()和Reflect.set(),确保原型链和 this 行为一致
结合用户角色动态判断访问权限
权限不应硬编码在 handler 里,而应依赖运行时上下文。可将用户角色、权限列表作为闭包变量传入 Proxy:
- 构造 Proxy 时注入当前用户信息,例如
{ role: 'admin', permissions: ['user:read', 'user:delete'] } - 在 get 中根据属性名映射到对应权限项(如
user.password → 'user:read'),再查表判断 - 对方法调用(如
obj.delete())也可在 get 中返回带权限检查的包装函数
统一拦截多种操作增强控制力
仅靠 get/set 不足以覆盖全部访问场景。实际中常需组合多个 trap 实现完整防护:
阿里百炼大模型平台多人共享账号用量统计代理服务。解决公司共用账号时无法区分个人用量的问题。适用场景:1)部署用量统计代理;2)统计多人Token用量和调用次数;3)管理大模型API调用配额。
- 用 has 隐藏私有属性:当
prop in obj时返回false,让属性“不可见” - 用 ownKeys 过滤返回的属性列表,剔除非授权字段
- 用 deleteProperty 阻止删除关键属性,或要求管理员权限才允许
- 用 apply 拦截函数调用,统一做参数校验与权限前置检查
避免常见陷阱提升可靠性
Proxy 权限层看似简单,但几个细节处理不好会导致绕过或误拦:
- 不要直接用
target[prop],务必走Reflect.get(target, prop, receiver),否则继承链失效 - set trap 必须显式返回
true才算赋值成功;返回false或不返回会在严格模式下报错 - Proxy 只代理第一层,嵌套对象需递归代理或配合 get 动态创建子代理
- 谨慎使用 getPrototypeOf 或 isExtensible 等元操作 trap,多数权限场景无需干预










