40 lines
1.3 KiB
JavaScript
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 无法解析')
|
|
}
|
|
}
|