jwt文件本质是base64url编码的纯文本,应以二进制模式用std::ifstream读取为字符串,严格按两个'.'分割为三段,替换'-'→'+'、'_'→'/'并补足'='后base64解码,再交由nlohmann/json等解析为utf-8 json字符串。

JWT 文件本质是 Base64Url 编码的文本,不是“要解析的二进制文件”
很多人一看到 .jwt 后缀就以为需要特殊库或二进制读取——其实它只是个纯文本文件,内容形如 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c。C++ 里直接用 std::ifstream 读成字符串即可,无需任何“JWT 专用读取函数”。
常见错误现象:std::ifstream 读出来为空或乱码——大概率是没设 std::ios::binary 或没处理换行符;但更可能是文件本身带 BOM 或用了 CRLF 换行(尤其 Windows 保存的),导致后续 Base64 解码失败。
- 用
std::ifstream file("token.jwt", std::ios::in | std::ios::binary)打开,避免文本模式自动转换换行符 - 读取后用
std::string::erase清掉'\r'和首尾空白(std::isspace) - 不要用
std::getline逐行读——JWT 是单行字符串,换行会破坏签名部分
拆分 JWT 的三段必须用 '.' 分割,且严格校验段数
JWT 结构固定为三段:header.payload.signature,用 ASCII 点号分隔。不能用 JSON 解析器直接 parse 整个字符串,也不能依赖正则模糊匹配——点号必须是顶层分隔符,中间 Base64Url 字符串里也可能含点(虽然极少见,但规范允许)。
实操建议:
- 用
std::string::find_first_of('.', pos)找前两个点的位置,确保恰好有且仅有两个点,否则直接拒绝(throw std::invalid_argument("invalid JWT format")) - 三段分别存为
header_b64、payload_b64、signature_b64,注意 signature 部分**不可解码验证**——它只是原始字节的 Base64Url 编码,验证需用密钥重算 - 如果用第三方库(如
cpp-jwt),它内部也是这么拆的;自己手写时别图省事用std::stringstream+std::getline,容易漏掉空段
Base64Url 解码不能直接套用标准 Base64 库
JWT 使用 Base64Url 编码(RFC 4648 §5),和标准 Base64 有两个关键差异:'+' → '-','/' → '_',且末尾 '=' 填充可选。多数 C++ Base64 库(如 Boost、OpenSSL)默认不支持 Url 变体,直接 decode 会失败或返回垃圾数据。
解决方式:
- 手动替换:
std::replace(header_b64.begin(), header_b64.end(), '-', '+');,再替换'_'→'/' - 补足填充:计算长度 mod 4,缺几个就加几个
'='(例如长度 33 → 补 3 个'=') - 再交给 Base64 解码函数;若用 OpenSSL,调用
EVP_DecodeBlock前务必确认输入已标准化 - 注意:有些轻量库(如
base64.hpp)自带base64url_decode函数,优先选这类
解码后得到的是 JSON 字符串,不是结构化对象
Base64Url 解码 header_b64 和 payload_b64 后,得到的是 UTF-8 编码的 JSON 字符串(如 {"alg":"HS256","typ":"JWT"}),不是 C++ 对象。此时才轮到 JSON 库上场。
关键点:
- 选支持 UTF-8 且不强制转义的库:推荐
nlohmann/json(json::parse()直接接受std::string)或simdjson(更快,但需预分配 buffer) - 不要用
std::stoi或std::stod手动解析字段——exp字段是数字,但可能超int64_t范围;nlohmann::json的get<int64_t>()</int64_t>会安全截断,应改用get<double>()</double>或get<:int64_t>()</:int64_t>并检查is_number_integer() - 验证逻辑(如
exp是否过期)必须在 JSON 解析**之后**做,且注意系统时钟与 JWT 时间戳的时区一致性(JWT 时间戳是 Unix 秒,无时区)
真正麻烦的从来不是“怎么读文件”,而是 Base64Url 的细节处理和 JSON 时间字段的边界情况——这两个地方出错,token 会静默失效,很难 debug。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











