Files
2026-09-22 17:28:37 +08:00

40 lines
1.3 KiB
JavaScript

const EXACT_INTEGER_CLAIMS = [
'user_id',
'userId',
'tenant_id',
'tenantId',
'operator_tenant_id',
'membership_id',
'overseas_warehouse_id',
'domestic_warehouse_id',
'actor_user_id',
'actor_membership_id'
]
function decodeBase64Url(value) {
const normalized = value.replace(/-/g, '+').replace(/_/g, '/')
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '=')
if (typeof atob === 'function') return decodeURIComponent(Array.from(atob(padded), (char) => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`).join(''))
throw new Error('当前运行环境无法解析登录令牌')
}
function restoreExactIntegerClaims(payload, claims) {
for (const key of EXACT_INTEGER_CLAIMS) {
const match = payload.match(new RegExp(`"${key}"\\s*:\\s*(-?\\d+)`))
if (match) claims[key] = match[1]
}
return claims
}
export function decodeAccessToken(token) {
const payloadPart = String(token || '').split('.')[1]
if (!payloadPart) throw new Error('登录响应中的 accessToken 格式无效')
try {
const payload = decodeBase64Url(payloadPart)
return restoreExactIntegerClaims(payload, JSON.parse(payload))
} catch (error) {
if (error.message === '当前运行环境无法解析登录令牌') throw error
throw new Error('登录响应中的 accessToken 无法解析')
}
}