Service Worker无法直接访问localStorage或DOM,但可通过IndexedDB持久化权限数据、在fetch事件中轻量鉴权、按角色预缓存资源,并配合服务端二次校验实现客户端权限控制。

Service Worker 本身不能直接访问 localStorage 或 sessionStorage,也不具备 DOM 操作能力,因此无法在 Service Worker 线程中执行传统意义上的“客户端鉴权逻辑”(比如读取 token 后校验签名、解析 JWT payload 等)。但你可以借助其与页面的协作机制,结合持久化存储方案,在**请求拦截阶段实现精细化鉴权控制**——关键在于把鉴权所需的凭证和策略“前置化”“状态化”“可验证化”。
鉴权凭证需由主页面注入并持久化
Service Worker 运行在独立线程,不共享页面上下文。所以 token、权限列表、过期时间等敏感信息必须由页面主动写入持久化存储,并确保 Service Worker 能安全读取:
- 推荐使用 IndexedDB 存储结构化鉴权数据(如 { userId, token, permissions: ['read:order', 'write:user'], expiresAt: 1747892000 }),因其容量大、支持事务、可异步读取,且能被 Service Worker 访问
- 避免用 localStorage:Service Worker 无法同步读取,且 5MB 容量和字符串-only 限制不利于权限树或策略规则存储
- 页面登录成功后,立即将解密/校验后的权限数据写入 IndexedDB,并触发
postMessage通知 Service Worker 刷新缓存策略或更新拦截逻辑
在 fetch 事件中做轻量级、可缓存的鉴权判断
Service Worker 的 fetch 事件是鉴权落地的核心环节。这里不做复杂计算,而是基于预置规则快速决策:
- 对受保护 API 路径(如
/api/v1/orders)拦截请求,从 IndexedDB 中查出当前用户权限(注意:需用event.waitUntil()包裹异步操作) - 检查权限字段是否包含对应 action,例如:
permissions.includes('read:order') - 若无权限,直接返回 403 响应(可复用预缓存的错误页),不发起网络请求;若有权限,则放行或附加认证头(通过
request.clone()+new Request()注入 Authorization) - 权限数据可加内存缓存(如用全局 Map 存 key→permission 对象),减少重复 DB 查询,但需配合页面 postMessage 失效机制
利用 Cache API 实现权限感知的资源隔离
不同角色看到的页面、菜单、按钮可能不同。单纯靠前端渲染隐藏不安全——Service Worker 可以在安装/激活阶段,按角色预缓存差异化资源:
- 注册时传入角色标识(如
navigator.serviceWorker.register('/sw.js', { type: 'module', scope: '/', updateViaCache: 'none' }),再由页面通过postMessage发送角色信息) - 在 install 事件中,根据角色打开不同 cache 名称(如
caches.open('admin-core-v1')vscaches.open('user-core-v1')),分别缓存对应 HTML、JS chunk - fetch 时,优先匹配对应角色 cache,未命中再 fallback 到通用 cache 或网络,实现静态资源级权限隔离
敏感操作需服务端二次确认,SW 不替代后端鉴权
Service Worker 的鉴权本质是“客户端策略执行”,不是安全边界。所有涉及资金、删除、权限变更等高危操作,必须:
- 在 fetch 拦截中强制添加
X-Client-Auth: verified等自定义 header,服务端据此识别“已过前端初筛” - 服务端仍须完整校验 session/token、RBAC/ABAC 规则、操作幂等性及业务风控逻辑
- Service Worker 可缓存鉴权失败的响应(如 403),但禁止缓存 200 成功响应中的敏感字段(如用户余额),防止离线篡改或泄露

















