JWT: โครงสร้าง การสร้าง และการตรวจสอบ
ถอดรหัสโครงสร้าง JWT ด้วยตนเอง สร้างโทเค็นที่ลงลายเซ็นด้วย secret และตรวจสอบเคลมโดยไม่ใช้เฟรมเวิร์ก
JWT: โครงสร้าง การสร้าง และการตรวจสอบ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
JWT คืออะไร
JSON Web Token (JWT) เป็นรูปแบบโทเค็นขนาดกะทัดรัดและปลอดภัยสำหรับ URL สำหรับส่งข้อมูลการอ้างสิทธิ์ระหว่างฝ่ายต่าง ๆ JWT จะถูกลงนาม (และอาจเข้ารหัสเพิ่มเติม) โดยมีข้อมูลครบในตัว จึงไม่จำเป็นต้องค้นหาฐานข้อมูลเพื่อยืนยันการอ้างสิทธิ์
โครงสร้าง JWT: Header.Payload.Signature
JWT มีสามส่วนที่เข้ารหัสด้วย Base64URL และคั่นด้วยจุด: header.payload.signature ส่วนหัวระบุอัลกอริทึม ข้อมูลเนื้อหาประกอบด้วยการอ้างสิทธิ์ และลายเซ็นใช้ตรวจสอบความถูกต้องครบถ้วน
// Example JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 <- header
// .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0 <- payload
// .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c <- signatureการถอดรหัสส่วนหัวและข้อมูลเนื้อหา
ถอดรหัสแต่ละส่วนด้วย Base64URL เพื่อดู JSON ข้อมูลเนื้อหาประกอบด้วย "การอ้างสิทธิ์" ซึ่งการอ้างสิทธิ์มาตรฐานได้แก่ sub (หัวข้อ), iss (ผู้ออก), exp (เวลาหมดอายุ) และ iat (เวลาที่ออกให้)
// Header:
{ "alg": "HS256", "typ": "JWT" }
// Payload:
{ "sub": "user-42", "name": "Alice", "role": "ADMIN",
"iat": 1716000000, "exp": 1716003600 }การสร้าง JWT ด้วยตนเอง (HS256)
สร้าง JSON ของส่วนหัวและข้อมูลเนื้อหา เข้ารหัสแต่ละส่วนด้วย Base64URL นำมาต่อกันด้วยจุด จากนั้นคำนวณ HMAC-SHA256 ของ header.payload และต่อผลลัพธ์เป็นลายเซ็น
String header = Base64.getUrlEncoder().withoutPadding()
.encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
String payload = Base64.getUrlEncoder().withoutPadding()
.encodeToString("{\"sub\":\"user-42\",\"exp\":9999999999}".getBytes());
String sigInput = header + "." + payload;
byte[] sig = computeHmac(secretKey, sigInput);
String jwt = sigInput + "." + Base64.getUrlEncoder().withoutPadding().encodeToString(sig);การตรวจสอบ JWT ด้วยตนเอง
แยกด้วยจุด ถอดรหัสส่วนหัวและข้อมูลเนื้อหา คำนวณ HMAC ใหม่จาก header.payload เปรียบเทียบกับลายเซ็น และตรวจสอบว่า exp อยู่ในอนาคต
String[] parts = jwt.split("\\.");
String sigInput = parts[0] + "." + parts[1];
byte[] expectedSig = computeHmac(secretKey, sigInput);
byte[] actualSig = Base64.getUrlDecoder().decode(parts[2]);
if (!MessageDigest.isEqual(expectedSig, actualSig)) throw new SecurityException("Invalid signature");
// Decode payload and check exp:
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]));
// parse JSON and check exp > nowการใช้ไลบรารี java-jwt (Auth0)
ไลบรารี com.auth0:java-jwt ช่วยให้การสร้างและตรวจสอบ JWT ง่ายขึ้นด้วย API แบบต่อเมธอด
// Create:
Algorithm alg = Algorithm.HMAC256(secretKey);
String token = JWT.create()
.withSubject("user-42")
.withClaim("role", "ADMIN")
.withExpiresAt(Instant.now().plusSeconds(3600))
.sign(alg);
// Verify:
JWTVerifier verifier = JWT.require(alg).withIssuer("my-service").build();
DecodedJWT decoded = verifier.verify(token);
System.out.println(decoded.getSubject());HS256 เทียบกับ RS256
HS256 ใช้คีย์สมมาตรร่วมกัน จึงเรียบง่าย แต่ทั้งผู้ออกและผู้ตรวจสอบต้องไว้วางใจซึ่งกันและกันเกี่ยวกับคีย์ ส่วน RS256 ใช้ RSA โดยลงนามด้วยคีย์ส่วนตัวและตรวจสอบด้วยคีย์สาธารณะ จึงเหมาะสำหรับสถาปัตยกรรมหลายบริการที่ทุกบริการสามารถตรวจสอบได้โดยไม่ต้องรู้คีย์ที่ใช้ลงนาม
การจัดเก็บ JWT: คุกกี้ HttpOnly เทียบกับ localStorage
จัดเก็บ JWT ในคุกกี้ HttpOnly (ไม่สามารถเข้าถึงจาก JS ได้ จึงป้องกันการขโมยจาก XSS) พร้อมแฟล็ก Secure และ SameSite=Strict หลีกเลี่ยง localStorage เนื่องจากการโจมตี XSS สามารถอ่านข้อมูลได้
// Set JWT as HttpOnly cookie in Spring:
ResponseCookie cookie = ResponseCookie.from("jwt", token)
.httpOnly(true).secure(true).sameSite("Strict")
.path("/").maxAge(3600).build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());โทเค็นรีเฟรช
JWT มีอายุสั้น (15 นาที) ส่วนโทเค็นรีเฟรช (โทเค็นทึบแสงที่จัดเก็บฝั่งเซิร์ฟเวอร์) มีอายุยาวกว่า ไคลเอ็นต์จะแลกโทเค็นรีเฟรชเป็น JWT ใหม่โดยไม่ต้องยืนยันตัวตนอีกครั้ง
ความท้าทายในการเพิกถอน JWT
JWT เป็นแบบไร้สถานะ จึงไม่มีการเพิกถอนในตัว ให้ใช้อายุสั้นร่วมกับรายการบล็อกของรหัส JWT ที่ถูกเพิกถอน (การอ้างสิทธิ์ jti) ใน Redis เพื่อรองรับการออกจากระบบก่อนหมดอายุ
// On logout, add the jti to a Redis blocklist with TTL = token expiry:
redis.set("revoked:" + jti, "1", ex, 3600);
// On verify, check blocklist:
if (redis.exists("revoked:" + decoded.getId())) throw new SecurityException("Token revoked");การผสานรวม JWT กับ Spring Security
ใน Spring Security ให้ใช้งาน JwtAuthenticationFilter extends OncePerRequestFilter เพื่อดึงข้อมูล ตรวจสอบ และกำหนดค่า SecurityContext จาก JWT ในแต่ละคำขอ
String token = request.getHeader("Authorization").replace("Bearer ","");
DecodedJWT decoded = verifier.verify(token);
String userId = decoded.getSubject();
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(userId, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);ตรวจสอบอย่างรวดเร็ว
ความแตกต่างเชิงโครงสร้างที่สำคัญระหว่างการลงนาม JWT แบบ HS256 และ RS256 คืออะไร
สรุปทบทวน
JWT = header.payload.signature (Base64URL) ลงนามด้วย HMAC (HS256) หรือ RSA (RS256) ตรวจสอบลายเซ็นและการอ้างสิทธิ์ exp จัดเก็บในคุกกี้ HttpOnly ใช้อายุสั้นร่วมกับโทเค็นรีเฟรช และเพิกถอนผ่านรายการบล็อก jti ใน Redis
คำถามที่พบบ่อย
บทเรียน “JWT: โครงสร้าง การสร้าง และการตรวจสอบ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “JWT: โครงสร้าง การสร้าง และการตรวจสอบ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “JWT: โครงสร้าง การสร้าง และการตรวจสอบ”
ถอดรหัสโครงสร้าง JWT ด้วยตนเอง สร้างโทเค็นที่ลงลายเซ็นด้วย secret และตรวจสอบเคลมโดยไม่ใช้เฟรมเวิร์ก คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “JWT: โครงสร้าง การสร้าง และการตรวจสอบ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การแฮชเชิงเข้ารหัสด้วย MessageDigest
- การเข้ารหัสแบบสมมาตร AES
- HMAC-SHA256 เพื่อความถูกต้องครบถ้วนของข้อความ
- JWT: โครงสร้าง การสร้าง และการตรวจสอบ