Base64 ปลอดภัยสำหรับ URL
เข้ารหัสและถอดรหัส Base64 ปลอดภัยสำหรับ URL (Base64url)
ข้อความธรรมดา
Base64
การเข้ารหัส Base64url คืออะไร?
Base64url คือรูปแบบหนึ่งของการเข้ารหัส Base64 ที่ออกแบบมาโดยเฉพาะสำหรับใช้งานใน URL, ชื่อไฟล์ และบริบทอื่นๆ ที่อักขระมาตรฐาน Base64 อย่าง + และ / ทำให้เกิดปัญหา กำหนดไว้ใน RFC 4648 ส่วนที่ 5, Base64url แทนที่ + ด้วย - (ยัติภังค์) และ / ด้วย _ (ขีดล่าง) และละเว้นอักขระ padding = ท้ายสตริง ผลลัพธ์คือสตริงที่สามารถฝังโดยตรงใน URL query parameter, ชื่อไฟล์ หรือ HTTP header โดยไม่ต้องเข้ารหัสเปอร์เซ็นต์เพิ่มเติม
Base64 มาตรฐาน (RFC 4648 ส่วนที่ 4) ใช้อักขระ 64 ตัว ได้แก่ A-Z, a-z, 0-9, + และ / อักขระ + และ / มีความหมายพิเศษใน URL: + จะถูกตีความเป็นช่องว่างใน query string (application/x-www-form-urlencoded) และ / เป็นตัวคั่นเส้นทาง การใช้ Base64 มาตรฐานภายใน URL จึงต้องเข้ารหัสอักขระเหล่านี้เป็นเปอร์เซ็นต์ (%2B, %2F) ซึ่งทำให้สตริงยาวขึ้นและอ่านยากขึ้น Base64url แก้ปัญหานี้ได้อย่างสมบูรณ์โดยใช้อักขระที่ปลอดภัยสำหรับ URL ตั้งแต่แรก
การใช้งาน Base64url ที่โดดเด่นที่สุดคือใน JSON Web Token (JWT) ทั้งสามส่วนของ JWT — header, payload และ signature — ถูกเข้ารหัสด้วย Base64url OAuth 2.0 PKCE code verifier, WebAuthn challenge value และ API token scheme หลายรูปแบบก็พึ่งพา Base64url เช่นกัน การเข้าใจการเข้ารหัสนี้เป็นสิ่งสำคัญสำหรับนักพัฒนาที่ทำงานกับการยืนยันตัวตน, การอนุญาต หรือการแลกเปลี่ยนข้อมูลแบบเข้ารหัส
ทำไมต้องใช้เครื่องมือ Base64url นี้?
แปลงระหว่าง Base64url กับข้อความหรือข้อมูลไบนารีโดยตรงในเบราว์เซอร์ของคุณ รองรับทั้งการเข้ารหัสและถอดรหัส พร้อมจัดการ padding และการแทนที่อักขระโดยอัตโนมัติ
กรณีการใช้งาน Base64url
Base64 มาตรฐาน เทียบกับ Base64url
Base64url แตกต่างจาก Base64 มาตรฐานใน 3 ประเด็นเท่านั้น อัลกอริทึมการเข้ารหัสเหมือนกัน — เปลี่ยนเพียง alphabet และพฤติกรรม padding:
| คุณสมบัติ | มาตรฐาน (RFC 4648 §4) | Base64url (RFC 4648 §5) |
|---|---|---|
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | = (required) | Omitted |
ความแตกต่าง 3 ประการนี้หมายความว่าการแปลงระหว่าง Base64 มาตรฐานกับ Base64url เป็นเรื่องง่าย: แทนที่ + ด้วย -, / ด้วย _ และลบอักขระ = ท้ายสตริง ในทางกลับกัน แทนที่ - ด้วย +, _ ด้วย / และเพิ่ม padding กลับเพื่อให้ความยาวเป็นทวีคูณของ 4 ภาษาส่วนใหญ่มีการรองรับ Base64url ในตัว ทำให้ไม่จำเป็นต้องแปลงด้วยตนเอง
ตารางเปรียบเทียบการเข้ารหัส
ตารางด้านล่างแสดงข้อมูล input เดียวกันที่เข้ารหัสด้วย Base64 มาตรฐานและ Base64url สังเกตว่าอักขระ padding (=) ถูกลบออก และ + / / ถูกแทนที่ด้วย - / _ ในรูปแบบที่ปลอดภัยสำหรับ URL:
| Input | Base64 มาตรฐาน | Base64url (ไม่มี padding) |
|---|---|---|
| Hello | SGVsbG8= | SGVsbG8 |
| A | QQ== | |
| 1+1=2 | MSsxPTI= | MSsxPTI |
| subject?ref=1 | c3ViamVjdD9yZWY9MQ== | c3ViamVjdD9yZWY9MQ |
| ð (thumbs up) | 8J+RjQ== | 8J-RjQ |
ตัวอย่างโค้ด
วิธีเข้ารหัสและถอดรหัสสตริง Base64url ในภาษายอดนิยม ทุกตัวอย่างผลิตผลลัพธ์ที่ปลอดภัยสำหรับใช้ใน URL, ชื่อไฟล์ และ HTTP header:
// Encode to Base64url
function toBase64url(str) {
return btoa(unescape(encodeURIComponent(str)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
}
toBase64url('Hello!') // → "SGVsbG8h"
// Decode from Base64url
function fromBase64url(b64url) {
const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/')
const pad = (4 - b64.length % 4) % 4
return decodeURIComponent(escape(atob(b64 + '='.repeat(pad))))
}
fromBase64url('SGVsbG8h') // → "Hello!"// Native base64url support since Node 15.7
const encoded = Buffer.from('Hello!').toString('base64url')
// → "SGVsbG8h"
const decoded = Buffer.from('SGVsbG8h', 'base64url').toString()
// → "Hello!"
// Decode a JWT payload
const jwt = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0...'
const payload = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString())
// → { sub: "1234567890" }import base64
# Encode to Base64url (no padding)
encoded = base64.urlsafe_b64encode(b'Hello!').rstrip(b'=').decode()
# → "SGVsbG8h"
# Decode from Base64url (re-add padding)
def b64url_decode(s: str) -> bytes:
s += '=' * (4 - len(s) % 4) # restore padding
return base64.urlsafe_b64decode(s)
b64url_decode('SGVsbG8h') # → b'Hello!'package main
import (
"encoding/base64"
"fmt"
)
func main() {
// Encode to Base64url (no padding)
encoded := base64.RawURLEncoding.EncodeToString([]byte("Hello!"))
fmt.Println(encoded) // → "SGVsbG8h"
// Decode from Base64url
decoded, _ := base64.RawURLEncoding.DecodeString("SGVsbG8h")
fmt.Println(string(decoded)) // → "Hello!"
}