Proxy 无法直接拦截原生 localStorage 的读写,因其为非可扩展对象且属性不可劫持;必须通过封装代理对象,用 apply 捕获器拦截 getItem/setItem 等方法调用,并结合动态权限校验实现安全访问。

不能直接用 Getter/Setter 拦截对 localStorage 的读写操作,因为 localStorage 是一个原生浏览器 API 对象,其属性(如 getItem、setItem、key 等)是只读方法或内部不可枚举属性,无法通过常规的 Object.defineProperty 或 Proxy 对其自身做有效拦截——除非你**不直接操作原生 localStorage,而是封装一层代理对象**。
用 Proxy 封装 localStorage 接口(推荐)
最可靠的方式是创建一个代理对象,把所有对 localStorage 的调用重定向到该代理,并在其中加入权限校验逻辑:
- 用
new Proxy({})创建一个空对象,然后在get和set捕获器中判断访问的是不是getItem/setItem等方法,再委托给原生 localStorage - 在
set捕获器中可拦截赋值(如storage.xxx = 'val'),但注意:这不适用于标准 localStorage 写法(localStorage.setItem(k,v)) - 真正实用的是对方法调用的拦截 —— 所以应重点使用
apply捕获器,拦截getItem、setItem等函数调用
实现带鉴权的 localStorage 代理示例
下面是一个轻量、可扩展的封装:
const createSecureStorage = (options = {}) => {
const {
canRead = () => true,
canWrite = () => true,
onUnauthorized = (type, key) => console.warn(`Blocked ${type} access to "${key}"`)
} = options;
<p>const handler = {
get(target, prop) {
if (prop === 'getItem' || prop === 'setItem' || prop === 'removeItem' || prop === 'clear' || prop === 'key' || prop === 'length') {
return function(https://www.php.cn/link/1f1bf7748e7e06682e348b22a722266a) {
const key = args[0];
if (prop === 'setItem' && !canWrite(key)) {
onUnauthorized('write', key);
return;
}
if ((prop === 'getItem' || prop === 'removeItem') && !canRead(key)) {
onUnauthorized('read', key);
return null;
}
return localStorage<a href="https://www.php.cn/link/1f1bf7748e7e06682e348b22a722266a">prop</a>;
};
}
return localStorage[prop];
}
};</p><p>return new Proxy({}, handler);
};</p><p>// 使用
const storage = createSecureStorage({
canRead: (key) => key.startsWith('public<em>') || isAuthenticated(),
canWrite: (key) => key.startsWith('user</em>') && isAuthenticated()
});
这样调用 storage.getItem('user_token') 就会自动校验权限,非法请求被静默拒绝或记录。
为什么不能直接代理 localStorage 本身?
因为:
-
localStorage是一个Storage实例,其原型链受浏览器保护,无法用Object.defineProperty劫持setItem等方法 - 尝试
new Proxy(localStorage, handler)在多数浏览器中会抛出TypeError: Cannot proxy a non-extensible object - 即使某些环境允许,也无法保证所有属性/方法都被捕获(例如
length、key(i)等可能绕过代理)
补充建议:配合 Token 或上下文做动态鉴权
权限不应硬编码,而应结合运行时状态:
- 从内存变量(如
currentUserRole)、JWT 解析结果,或异步检查接口中获取当前权限 - 对敏感键名(如
'auth_token'、'admin_config')做白名单/黑名单匹配 - 可记录未授权行为并上报,用于审计
不复杂但容易忽略:真正的拦截点不在 localStorage 本体,而在你代码中每一次对它的调用入口。封装 + Proxy + 权限函数,才是可控、可维护的解法。

















