背景与价值SAML在企业SSO广泛使用。统一签名与声明校验可防止伪造与重放,ACS端点匹配保障回调安全。统一规范验签算法:`RSA-SHA256`或`ECDSA-SHA256`,拒绝弱算法。Issuer/Audience:与配置严格一致,ACS精确匹配。时间窗口:`NotBefore/NotOnOrAfter` 提供±300秒容忍。核心实现断言解析与校验type Conditions = { NotBefore: number; NotOnOrAfter: number } type Claims = { Issuer: string; Audience: string; Subject: string; Conditions: Conditions } function timeNow(): number { return Math.floor(Date.now() / 1000) } function within(c: Conditions, leeway: number): boolean { const n = timeNow(); return n + leeway >= c.NotBefore && n - leeway <= c.NotOnOrAfter } function claimsOk(c: Claims, expected: { issuer: string; audience: string; acs: string; leeway: number; recipient: string }): boolean { if (c.Issuer !== expected.issuer) return false if (c.Audience !== expected.audience) return false if (!within(c.Conditions, expected.leeway)) return false return true } 签名与ACS匹配(示意)function base64ToBuf(s: string): ArrayBuffer { const b = atob(s); const u = new Uint8Array(b.length); for (let i=0;i<b.length;i++) u[i]=b.charCodeAt(i); return u.buffer } async function importPublicKey(spki: ArrayBuffer, type: 'RS256'|'ES256'): Promise<CryptoKey> { return crypto.subtle.importKey('spki', spki, type==='RS256'?{ name:'RSASSA-PKCS1-v1_5', hash:'SHA-256'}:{ name:'ECDSA', namedCurve:'P-256' }, false, ['verify']) } async function verifyXmlSig(sigB64: string, data: ArrayBuffer, key: CryptoKey, type: 'RS256'|'ES256'): Promise<boolean> { const sig = base64ToBuf(sigB64); return crypto.subtle.verify(type==='RS256'?{ name:'RSASSA-PKCS1-v1_5', hash:'SHA-256'}:{ name:'ECDSA', hash:'SHA-256' }, key, sig, data) } function acsAllowed(url: string, expect: string): boolean { try { const u = new URL(url); return (u.origin + u.pathname) === expect } catch { return false } } 落地建议验签算法限定为强算法并从可信来源加载公钥;ACS端点精确匹配。`Issuer/Audience` 严格一致并引入±300秒容忍窗口,缓解时钟偏移。验证清单断言验签是否成功;`Issuer/Audience` 是否匹配。`NotBefore/NotOnOrAfter` 是否在容忍窗口内;ACS是否精确匹配。

发表评论 取消回复