C++中的JWT令牌:jwt-cpp库
JSON Web Token (JWT) 是一种在各方之间以JSON对象形式传递信息的紧凑且自包含的方式。在C++中,有多个库可用于处理JWT,其中最流行且方便的一个是jwt-cpp。它提供了简单的API,用于使用各种算法(HMAC、RSA、ECDSA)创建、签名和验证JWT令牌。
在本文中,我们将探讨jwt-cpp库的主要功能,学习如何创建和验证令牌,并分析常见任务的代码示例。
安装jwt-cpp
jwt-cpp库是仅头文件(header-only)的,这简化了其集成到项目中的过程。要安装,只需克隆仓库:
git clone https://github.com/Thalhammer/jwt-cpp.git然后将include文件夹的路径添加到编译器的设置中。如果您使用CMake,连接方式如下:
add_subdirectory(jwt-cpp)target_link_libraries(your_project jwt-cpp)该库依赖于OpenSSL和jsoncpp(或nlohmann/json),因此请确保它们已安装。
基本创建JWT令牌
最简单的示例是使用HMAC-SHA256算法创建令牌。可以向令牌添加标准字段(iss、sub、exp、iat)和自定义声明。
#include <jwt-cpp/jwt.h>#include <iostream>
int main() { // 创建令牌 auto token = jwt::create() .set_issuer("auth0") .set_subject("1234567890") .set_issued_at(std::chrono::system_clock::now()) .set_expires_at(std::chrono::system_clock::now() + std::chrono::hours{1}) .set_payload_claim("name", jwt::claim(std::string("John Doe"))) .sign(jwt::algorithm::hs256{"secret-key"});
std::cout << "令牌: " << token << std::endl; return 0;}结果将得到一个由三部分(header、payload、signature)组成的字符串,各部分用点分隔。
验证令牌
要验证令牌的真实性,必须使用相同的密钥(或RSA的公钥)。验证示例:
#include <jwt-cpp/jwt.h>#include <iostream>
int main() { std::string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // 您的令牌
try { auto decoded = jwt::decode(token); // 验证签名 auto verifier = jwt::verify() .allow_algorithm(jwt::algorithm::hs256{"secret-key"}) .with_issuer("auth0");
verifier.verify(decoded);
// 提取数据 std::cout << "令牌有效!" << std::endl; std::cout << "Subject: " << decoded.get_subject() << std::endl; std::cout << "Name: " << decoded.get_payload_claim("name").as_string() << std::endl; } catch (const std::exception& e) { std::cerr << "验证错误: " << e.what() << std::endl; }
return 0;}重要提示:如果令牌过期(exp)、被篡改或使用其他密钥签名,将抛出异常。
使用RSA(非对称加密)
对于更安全的系统,通常使用RSA。在这种情况下,令牌使用私钥签名,并使用公钥验证。
#include <jwt-cpp/jwt.h>#include <fstream>#include <sstream>
int main() { // 从文件读取私钥 std::ifstream priv_file("private.pem"); std::stringstream priv_ss; priv_ss << priv_file.rdbuf(); std::string private_key = priv_ss.str();
// 使用RSA创建令牌 auto token = jwt::create() .set_issuer("myapp") .set_subject("user123"