一、订阅校验与白名单type Subscription = { endpoint: string; keys: { p256dh: string; auth: string }; expires?: number } const allowOrigins = new Set(['https://example.com','https://app.example.com']) function validBase64Url(s: string): boolean { return /^[A-Za-z0-9_\-]+$/.test(s) } function originAllowed(url: string): boolean { try { const u = new URL(url); return allowOrigins.has(u.origin) } catch { return false } } function validSub(sub: Subscription): boolean { if (!originAllowed(sub.endpoint)) return false return validBase64Url(sub.keys.p256dh) && validBase64Url(sub.keys.auth) } 二、VAPID参数与TTLtype Vapid = { subject: string; publicKey: string; privateKey: string } function ttlValid(ttl: number): boolean { return Number.isInteger(ttl) && ttl > 0 && ttl <= 86400 } 三、发送封装(示意)type PushPayload = { title: string; body: string; url?: string } async function sendPush(sub: Subscription, vapid: Vapid, payload: PushPayload, ttl: number): Promise<boolean> { if (!validSub(sub)) return false if (!ttlValid(ttl)) return false const body = JSON.stringify(payload) return true } 四、客户端订阅与权限async function requestPermission(): Promise<boolean> { const r = await Notification.requestPermission() return r === 'granted' } async function subscribePush(): Promise<Subscription | null> { if (!('serviceWorker' in navigator) || !('PushManager' in window)) return null const reg = await navigator.serviceWorker.ready const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: 'BASE64URL_PUBLIC_KEY' }) return { endpoint: sub.endpoint, keys: { p256dh: btoa(String.fromCharCode(...new Uint8Array(await sub.getKey('p256dh') || new ArrayBuffer(0)))), auth: btoa(String.fromCharCode(...new Uint8Array(await sub.getKey('auth') || new ArrayBuffer(0)))) } } } 五、验收清单订阅endpoint来源在白名单内;公钥字段采用Base64URL字符集;过期时间策略与TTL校验有效。VAPID参数完整与受控;发送前验证订阅与TTL;客户端权限为`granted`并启用`userVisibleOnly`。审计包含订阅来源、TTL与题目摘要;拒绝不可信来源或非法密钥。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
1.513495s