Base64 an toàn URL
Mã hóa và giải mã Base64 an toàn URL (Base64url)
Văn bản thuần
Base64
Base64url Encoding là gì?
Base64url là một biến thể của mã hóa Base64, được thiết kế đặc biệt để sử dụng trong URL, tên tệp và các ngữ cảnh khác mà các ký tự Base64 tiêu chuẩn + và / gây ra sự cố. Được định nghĩa trong RFC 4648 Mục 5, Base64url thay thế + bằng - (gạch ngang) và / bằng _ (gạch dưới), đồng thời bỏ qua các ký tự padding = ở cuối. Kết quả là một chuỗi có thể nhúng trực tiếp vào tham số truy vấn URL, tên tệp hoặc HTTP header mà không cần mã hóa phần trăm bổ sung.
Base64 tiêu chuẩn (RFC 4648 Mục 4) sử dụng 64 ký tự: A-Z, a-z, 0-9, + và /. Các ký tự + và / được dành riêng trong URL: + được hiểu là dấu cách trong query string (application/x-www-form-urlencoded), và / là dấu phân cách đường dẫn. Do đó, việc sử dụng Base64 tiêu chuẩn bên trong URL đòi hỏi phải mã hóa phần trăm các ký tự này (%2B, %2F), làm tăng độ dài chuỗi và khó đọc hơn. Base64url loại bỏ hoàn toàn vấn đề này bằng cách sử dụng các ký tự an toàn cho URL ngay từ đầu.
Ứng dụng nổi bật nhất của Base64url là trong JSON Web Token (JWT). Cả ba phần của JWT — header, payload và signature — đều được mã hóa Base64url. PKCE code verifier của OAuth 2.0, giá trị challenge của WebAuthn và nhiều sơ đồ API token cũng dựa vào Base64url. Hiểu rõ mã hóa này là thiết yếu với bất kỳ nhà phát triển nào làm việc với xác thực, phân quyền hoặc trao đổi dữ liệu mật mã.
Tại sao dùng công cụ Base64url này?
Chuyển đổi giữa Base64url và dữ liệu văn bản hoặc nhị phân trực tiếp trong trình duyệt. Hỗ trợ cả mã hóa lẫn giải mã, với xử lý tự động padding và thay thế ký tự.
Các trường hợp sử dụng Base64url
So sánh Base64 tiêu chuẩn và Base64url
Base64url khác Base64 tiêu chuẩn ở đúng ba điểm. Thuật toán mã hóa hoàn toàn giống nhau — chỉ bảng chữ cái và hành vi padding thay đổi:
| Tính năng | Tiêu chuẩn (RFC 4648 §4) | Base64url (RFC 4648 §5) |
|---|---|---|
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | = (required) | Omitted |
Ba sự khác biệt này có nghĩa là việc chuyển đổi giữa Base64 tiêu chuẩn và Base64url rất đơn giản: thay + bằng -, / bằng _, và loại bỏ các ký tự = ở cuối. Chiều ngược lại: thay - bằng +, _ bằng /, và thêm lại padding để độ dài là bội số của 4. Hầu hết các ngôn ngữ cung cấp hỗ trợ Base64url gốc, khiến việc chuyển đổi thủ công là không cần thiết.
Bảng so sánh mã hóa
Bảng dưới đây hiển thị cùng một đầu vào được mã hóa bằng Base64 tiêu chuẩn và Base64url. Chú ý cách các ký tự padding (=) bị loại bỏ và + / / được thay thế bằng - / _ trong biến thể an toàn URL:
| Đầu vào | Base64 tiêu chuẩn | Base64url (không padding) |
|---|---|---|
| Hello | SGVsbG8= | SGVsbG8 |
| A | QQ== | |
| 1+1=2 | MSsxPTI= | MSsxPTI |
| subject?ref=1 | c3ViamVjdD9yZWY9MQ== | c3ViamVjdD9yZWY9MQ |
| ð (thumbs up) | 8J+RjQ== | 8J-RjQ |
Ví dụ mã
Cách mã hóa và giải mã chuỗi Base64url trong các ngôn ngữ phổ biến. Mọi ví dụ đều tạo ra đầu ra an toàn để dùng trong URL, tên tệp và 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!"
}