关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。我们查阅了 RFC 7519、Microsoft identity platform 的现行资料以及现有的 Daily-Code-Samples,在不使用真实访问令牌的情况下仅观察 JWT 的结构。
验证状态:📘 已确认官方信息·PowerShell 执行未确认
JWT 的“部分内容可见”与“它是受信任的令牌”是两码事。如果不粘贴实际的 Microsoft Entra 访问令牌,而是创建一个完全的虚拟 header.payload.signature 并亲身体验 Base64URL 解码,您就会明白其中的区别。
首先运行
我们不使用真实令牌,仅创建用于教育目的的未签名数据。
function To-Base64Url([string]$Text) {
$bytes = [Text.Encoding]::UTF8.GetBytes($Text)
[Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+','-').Replace('/','_')
}
$header = '{"alg":"none","typ":"JWT"}'
$payload = '{"sub":"demo-user","role":"reader"}'
$token = "$(To-Base64Url $header).$(To-Base64Url $payload)."
Write-Host '[DUMMY]'
Write-Host $token
Write-Host '[SUCCESS] 3つの部分を持つ教育用データを作成しました'
JWT 标准为 RFC 7519。
通过查看这里
. 进行分隔,会分为三个部分。
header.payload.signature
本次的末尾是空的。alg=none 因为这是用于教育目的的未签名数据,所以不能用于身份验证目的。
flowchart LR
H[header JSON] --> E1[Base64URL]
P[payload JSON] --> E2[Base64URL]
E1 --> J[header.payload.signature]
E2 --> J
J --> D[decodeして内容を読む]
D --> N[署名検証とは別]
尝试解码
Base64URL 与普通的 Base64 在字符和填充的处理上略有不同。在完整版示例中,补充填充后再转换回 UTF-8。
function From-Base64Url([string]$Text) {
$b64 = $Text.Replace('-','+').Replace('_','/')
switch ($b64.Length % 4) {
2 { $b64 += '==' }
3 { $b64 += '=' }
0 { }
default { throw 'Base64URLの長さが不正です' }
}
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($b64))
}
$parts = $token.Split('.')
Write-Host "[RESULT] header = $(From-Base64Url $parts[0])"
Write-Host "[RESULT] payload = $(From-Base64Url $parts[1])"
尝试修改一处
将虚拟 payload 的 role 从 reader 更改为 writer。令牌字符串和解码结果都会轻松改变。
这一点很重要。能够阅读/被篡改与拥有正确的签名是两码事。在带签名的 JWT 中,接收方会验证签名等以判断其可靠性。
Microsoft 访问令牌的注意事项
Microsoft 指导将访问令牌视为机密凭据。此外,客户端应用程序基本应将访问令牌视为不透明字符串(opaque string),因此不要理所当然地认为面向 Microsoft API 的令牌总是应当由自己解码的 JWT,这样更安全。
请勿将其作为将真实令牌粘贴到在线解码器的教材。
如果在工作中应用
切勿将令牌输出到日志中
切勿将真实令牌粘贴到第三方网站
切勿将解码称为签名验证
切勿混淆 JWT / JWS / JWE
在依赖令牌内容之前,请先确认目标 API 的官方规范
结构观察使用虚拟数据就足够了。
GitHub 示例
官方信息·第一手资料
总结
能够对 JWT 的一部分进行解码并不意味着加密或签名验证。通过使用完全的虚拟数据尝试“读取 → 修改一处”,您可以将 payload 的可读性与令牌的可靠性分开来理解。

