签署与验证 JWT
学习 JWT 签名背后的密码学原理,以及如何验证令牌的完整性和真实性。
签署与验证 JWT 是 CoddyKit 上的免费 Spring Security 6 & JWT Authentication 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Spring Security 6 & JWT Authentication 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Spring Security 6 & JWT Authentication 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
What is JWT Signing?
JSON Web Tokens (JWTs) are powerful, but how do we trust them? Signing is the answer! It's a cryptographic process that ensures a token hasn't been tampered with and comes from a trusted source.
- Integrity: Confirms the token's content hasn't been changed since it was issued.
- Authenticity: Verifies the token was issued by the expected sender.
Without a signature, anyone could create or alter a JWT!
Keys to Security: The Secret
For symmetric signing algorithms like HMAC (e.g., HS256), a single secret key is used. This key is known only to the issuer and the intended verifier(s).
- The secret key is a string of bytes, crucial for both signing and verifying.
- It must be kept highly confidential.
- If the secret key is compromised, your JWTs are no longer secure!
Algorithms: HS256 & RS256
JWTs use cryptographic algorithms to create the signature. The algorithm type is specified in the token's header.
- HS256 (HMAC SHA-256): A symmetric algorithm. Uses a single secret key for both signing and verification. Simpler to implement.
- RS256 (RSA SHA-256): An asymmetric algorithm. Uses a private key for signing and a public key for verification. More complex but better for distributed systems.
We'll focus on HS256 for our examples due to its simplicity.
Building the Signature (HS256)
The signature is created by combining the Base64Url encoded header, the Base64Url encoded payload, and your secret key using the chosen algorithm.
- Take the Base64Url encoded header.
- Take the Base64Url encoded payload.
- Concatenate them with a dot:
encodedHeader + "." + encodedPayload. - Hash this combined string using HMAC SHA-256 with your secret key.
- Base64Url encode the resulting hash to get the final signature.
Result: encodedHeader.encodedPayload.signature
Code: Generating HS256 Signature
Here's a Java example to generate an HS256 signature for a JWT. Notice how the secret key is essential for the hashing process.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class JwtSigner {
public static void main(String[] args) throws Exception {
String encodedHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; // {"alg":"HS256","typ":"JWT"}
String encodedPayload = "eyJpZCI6MSwicm9sZSI6InVzZXIifQ"; // {"id":1,"role":"user"}
String secret = "coddykit-secret-lesson-key-1234567890";
String dataToSign = encodedHeader + "." + encodedPayload;
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
hmacSha256.init(secretKey);
byte[] signatureBytes = hmacSha256.doFinal(dataToSign.getBytes("UTF-8"));
String encodedSignature = Base64.getUrlEncoder().withoutPadding().encodeToString(signatureBytes);
System.out.println("Data to Sign: " + dataToSign);
System.out.println("Generated Signature: " + encodedSignature);
System.out.println("Full JWT: " + dataToSign + "." + encodedSignature);
}
}Verifying a JWT's Signature
Verification is the reverse process of signing. When you receive a JWT, you need to ensure its signature is valid.
- Separate the received JWT into its three parts: header, payload, and signature.
- Reconstruct the "data to sign" string:
encodedHeader + "." + encodedPayload. - Using the same secret key and algorithm, calculate a new signature from this data.
- Compare your newly calculated signature with the signature provided in the JWT.
If they match, the token is valid and untampered! If not, it's invalid.
Secure Key Management
The security of your JWTs critically depends on how well you manage your signing keys. A compromised key invalidates all your security efforts!
- Confidentiality: Keep secret keys private. Never hardcode them in client-side code.
- Rotation: Regularly change your keys to limit the impact of a potential compromise.
- Strength: Use strong, random, and sufficiently long keys.
- Store keys in secure environments, like environment variables or dedicated key management services.
Code: Verifying HS256 Signature
This example demonstrates how to verify a JWT's signature. We use the same secret key to recalculate the signature and compare it against the one in the token.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class JwtVerifier {
public static void main(String[] args) throws Exception {
String jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6InVzZXIifQ.qS6pQ_6_q-P_5_o-O_6_n-N_7_m-M_8_l-L_9_k-K_0_j-J_1_i-I_2_h-H_3_g-G_4_f-F_5_e-E_6_d-D_7_c-C_8_b-B_9_a-A";
String secret = "coddykit-secret-lesson-key-1234567890";
String[] parts = jwt.split("\\.");
String encodedHeader = parts[0];
String encodedPayload = parts[1];
String receivedSignature = parts[2];
String dataToSign = encodedHeader + "." + encodedPayload;
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
hmacSha256.init(secretKey);
byte[] calculatedSignatureBytes = hmacSha256.doFinal(dataToSign.getBytes("UTF-8"));
String calculatedSignature = Base64.getUrlEncoder().withoutPadding().encodeToString(calculatedSignatureBytes);
if (calculatedSignature.equals(receivedSignature)) {
System.out.println("Signature is VALID!");
} else {
System.out.println("Signature is INVALID!");
System.out.println("Received: " + receivedSignature);
System.out.println("Calculated: " + calculatedSignature);
}
}
}Symmetric vs. Asymmetric Signing
While HS256 (HMAC SHA-256) uses a shared secret, RS256 (RSA SHA-256) and ES256 (ECDSA SHA-256) use key pairs.
- Symmetric (e.g., HS256): Same key for signing and verifying. Best for single-service applications or when the verifier is also the issuer.
- Asymmetric (e.g., RS256, ES256): Private key for signing, public key for verifying. Ideal for distributed systems where multiple services need to verify tokens issued by a central authority. The public key can be shared widely without compromising security.
Quick Check: JWT Security
You've learned about JWT signing and verification. Let's test your understanding.
Recap: Secure JWTs
Great job! We've demystified how JWTs are secured through signing and verification.
- Signing ensures a JWT's integrity and authenticity using a cryptographic algorithm and a secret key.
- HS256 (HMAC SHA-256) is a symmetric algorithm using a single shared secret.
- Verification involves recalculating the signature and comparing it to the received one.
- Secure key management is paramount for JWT security.
- Asymmetric algorithms like RS256 use key pairs for distributed verification.
Next up, we'll see how to integrate JWTs with Spring Security!
常见问题解答
「签署与验证 JWT」课时是免费的吗?
是的 — 「签署与验证 JWT」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Spring Security 6 & JWT Authentication 课程的其余内容,请升级到 CoddyKit PRO。 Spring Security 6 & JWT Authentication 课程共包含 4 节课。
「签署与验证 JWT」这节课中我会学到什么?
学习 JWT 签名背后的密码学原理,以及如何验证令牌的完整性和真实性。 你通过在浏览器中直接运行的动手代码来练习 Spring Security 6 & JWT Authentication,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Spring Security 6 & JWT Authentication 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Spring Security 6 & JWT Authentication 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「签署与验证 JWT」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Spring Security 6 & JWT Authentication 课中编写并运行代码吗?
能。每节 Spring Security 6 & JWT Authentication 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。