慣性聚合 高效追蹤和閱讀你感興趣的部落格、新聞、科技資訊
閱讀原文 在慣性聚合中打開

推薦訂閱源

小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
T
Tailwind CSS Blog
Jina AI
Jina AI
量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
V
Visual Studio Blog
月光博客
月光博客

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python)
Base64 說明 — 它是什麼、何時使用,以及開發者常遇到的陷阱
William Andr · 2026-05-28 · via DEV Community

你看到一串以==結尾的長字串和數字,心想這是什麼。你將一個JWT貼到工具中,中間的部分大多可讀。你在HTML郵件中嵌入一張圖片,src屬性是一串密密麻麻的字元。你將PDF上傳到API,文件告訴你要「以Base64格式發送」。這些都是同一種編碼,大多數開發者使用它卻從未真正理解其作用。

本指南涵蓋了 Base64 的實際定義、使用時機、常見錯誤(包括最大的錯誤——誤以為它是加密)、URL 安全變體、填充規則,以及在每種主要語言中如何進行編碼和解碼。

Base64 的實際定義

Base64 是一種使用 64 個特定字元將二進位資料轉換為 ASCII 文字的編碼方式:A-Z, a-z,0-9,加上 +/= 字符用於結尾填充。每 3 個位元組的輸入會產生恰好 4 個 Base64 字元的輸出——這表示 Base64 會使資料大小增加約 33%。

Input bytes:   "Hi"                  (2 bytes: 0x48 0x69)
Binary:        01001000 01101001
Group in 6s:   010010 000110 1001(00)   ← last group padded with zeros
Base64 chars:  S      G      k    =     ← '=' = padding

Result:        "SGk="

進入全螢幕模式 退出全螢幕模式

數學原理:64個字元表示每個字元代表6位元。6位元(一個Base64字元)和8位元(一個位元組)的最小公倍數是24位元——即3個位元組或4個Base64字元。這就是為什麼Base64總是按4個輸出字元為一組運作,以及為什麼需要填充的原因。


最大的誤解:Base64不是加密。

這會同時吸引開發者和非開發者。Base64看起來像亂碼,因此感覺像是一個秘密。但其實它不是。任何人都可以立即解碼Base64——沒有密鑰、沒有密碼、不需要破解演算法。它是一種透明的轉換,就像用不同的字母系統書寫一樣。

// "Encrypted" password?
"cGFzc3dvcmQxMjM="

// Decoded in one line
atob("cGFzc3dvcmQxMjM=")
// → "password123"

進入全螢幕模式 退出全螢幕模式

Base64是編碼,不是加密。使用它來傳輸 透過純文字通道安全地傳送資料 ─ 切勿使用 hide 資料。若需保密性,請使用真正的加密技術:傳輸中的資料使用 AES、NaCl/libsodium 或 TLS。


何時使用 Base64

Base64 的存在是為了將二進位資料透過預期為文字的系統進行傳遞。最常見的情況:

將二進位資料嵌入 JSON 或 XML — 兩種格式都不支援原始位元組。接受檔案上傳作為 JSON 負載一部分的 API 使用 Base64 來表示檔案。

HTML/CSS 中的資料 URLdata:image/png;base64,iVBORw0KGgo... 讓你可以內嵌圖片而無需單獨的 HTTP 請求。適用於小型圖示和電子郵件簽名。

HTTP 基本認證Authorization 標頭將憑證傳送為Basic <base64-of-username:password>. 這也是一個完美的例子,說明為什麼 Base64 不是加密——基本驗證(Basic Auth)只有搭配 HTTPS 時才安全。

JWTs — JSON Web Token 由三個以點分隔的 Base64URL 編碼部分組成。標頭(header)和負載(payload)是可讀的 JSON;只有簽名(signature)是不透明的。

電子郵件附件 — SMTP 在技術上是一種 7 位元文字協定,因此自 MIME 標準以來,附件預設使用 Base64 編碼。

加密金鑰與憑證 — PEM 檔案(-----BEGIN CERTIFICATE----- 區塊)包裝了 Base64 編碼的二進位金鑰。


填補(Padding)— 為什麼有些 Base64 結尾有 =,有些沒有

=是填充字元。這是因為Base64以3個輸入位元組為一組進行編碼,但並非所有輸入都是3位元組的倍數。當輸入短少了1或2個位元組時,編碼器會用=字元填補輸出,使結果始終為4個字元的倍數。

Input length (mod 3)   Padding   Example
─────────────────────────────────────────
0 (multiple of 3)      none      "Man"  → "TWFu"
1                      ==        "M"    → "TQ=="
2                      =         "Ma"   → "TWE="

進入全螢幕模式 退出全螢幕模式

某些編碼器和協定會移除填充以節省位元組。JWT 就是如此——JWT 中的 Base64URL 編碼完全沒有填充。如果你手動從 JWT 中解碼 Base64,你可能需要在某些解碼器接受之前重新加上填充。

// JavaScript: add padding back to an unpadded Base64 string
function pad(b64) {
  const remainder = b64.length % 4;
  return remainder ? b64 + '='.repeat(4 - remainder) : b64;
}

進入全螢幕模式 退出全螢幕模式


Base64 與 Base64URL——對網路而言重要的變體

標準 Base64 使用+/作為其第62和第63個字符。兩者在URLs中都具有特殊含義:+在查詢字串中表示「空格」,且/是一個路徑分隔符號。將標準的Base64直接放入URL而不進一步編碼會導致問題。

Base64URL(定義於 RFC 4648)透過交換這些字元來解決此問題:+成為-,而/變成_。它通常也會省略填充。結果可以直接安全地放入URL、檔案名稱和HTTP標頭中。

Standard Base64:   "abc/d+ef=="
Base64URL:         "abc_d-ef"

// Convert one to the other
const toUrlSafe = (b64) => b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const fromUrlSafe = (b64u) => {
  const b64 = b64u.replace(/-/g, '+').replace(/_/g, '/');
  return pad(b64); // add padding back
};

進入全螢幕模式 退出全螢幕模式

JWT使用Base64URL。大多數現代令牌格式、OAuth狀態參數以及任何在URL中傳輸的內容也是如此。


在JavaScript中進行編碼和解碼

JavaScript 有兩個內建函式:btoa()(二進位轉 ASCII,編碼)和 atob()(ASCII 轉二進位,解碼)。這兩個名稱很容易混淆——因為它們對任意二進位資料的處理方式並不符合直覺。

// Simple ASCII strings — these work
btoa("Hello, world!");
// → "SGVsbG8sIHdvcmxkIQ=="

atob("SGVsbG8sIHdvcmxkIQ==");
// → "Hello, world!"

// Unicode strings — this BREAKS
btoa("héllo");
// → DOMException: invalid character

// Correct way for Unicode: encode to UTF-8 first
function utf8ToBase64(str) {
  return btoa(unescape(encodeURIComponent(str)));
}
function base64ToUtf8(b64) {
  return decodeURIComponent(escape(atob(b64)));
}

utf8ToBase64("héllo");   // → "aMOpbGxv"
base64ToUtf8("aMOpbGxv"); // → "héllo"

// Modern alternative (Node 16+, modern browsers)
const bytes = new TextEncoder().encode("héllo");
const b64 = btoa(String.fromCharCode(...bytes));

進入全螢幕模式 離開全螢幕模式

對於檔案上傳這類二進位資料,請使用 ArrayBuffer(Uint8Array)或 Uint8Array(ArrayBuffer):

// Convert a file to Base64 (browser)
async function fileToBase64(file) {
  const buffer = await file.arrayBuffer();
  const bytes = new Uint8Array(buffer);
  let binary = '';
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary);
}

// FileReader alternative — gives you a data URL
function fileToDataUrl(file) {
  return new Promise(resolve => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

進入全螢幕模式 退出全螢幕模式


Python 中的編碼與解碼

import base64

# Encode a string
encoded = base64.b64encode(b"Hello, world!")
# → b"SGVsbG8sIHdvcmxkIQ=="

# Decode
decoded = base64.b64decode(b"SGVsbG8sIHdvcmxkIQ==")
# → b"Hello, world!"

# URL-safe variant — for JWTs, URLs, filenames
url_safe = base64.urlsafe_b64encode(b"data with /and+chars")
# → b"ZGF0YSB3aXRoIC9hbmQrY2hhcnM="

# Encode a file
with open("photo.jpg", "rb") as f:
    encoded_file = base64.b64encode(f.read()).decode("ascii")

進入全螢幕模式 退出全螢幕模式


命令列中的編碼與解碼

# macOS and Linux — encode
echo -n "Hello, world!" | base64
# → SGVsbG8sIHdvcmxkIQ==

# Decode
echo "SGVsbG8sIHdvcmxkIQ==" | base64 -d
# → Hello, world!

# Encode a file
base64 photo.jpg > photo.txt

# Decode a file
base64 -d photo.txt > photo.jpg

# Watch out — many systems wrap output at 76 characters by default
# Use -w 0 (GNU) or no flag (BSD) to disable wrapping
echo -n "long content..." | base64 -w 0

進入全螢幕模式 退出全螢幕模式


SQL 中的編碼與解碼

-- PostgreSQL
SELECT encode('Hello, world!'::bytea, 'base64');
-- → SGVsbG8sIHdvcmxkIQ==

SELECT convert_from(decode('SGVsbG8sIHdvcmxkIQ==', 'base64'), 'UTF8');
-- → Hello, world!

-- MySQL 8+
SELECT TO_BASE64('Hello, world!');
-- → SGVsbG8sIHdvcmxkIQ==

SELECT FROM_BASE64('SGVsbG8sIHdvcmxkIQ==');
-- → Hello, world!

進入全螢幕模式 退出全螢幕模式


常見錯誤及其避免方法

換行陷阱。某些實作(特別是 MIME 和 OpenSSL)會在 Base64 輸出中每 64 或 76 個字元換行。其他實作則拒絕包含換行符的輸入。如果您在解碼看似有效的 Base64 時看到「無效字元」錯誤,請先去除空白字元。

填充不匹配。 JWT 與 URL 安全的 Base64 通常會省略填充。許多解碼器需要填充。如果解碼失敗,請計算需要新增多少個 = 字元:(4 - (length % 4)) % 4 個。

UTF-8 假設。 Base64 編碼的是位元組,而非字元。對字串進行編碼時,必須先確定它所使用的字元編碼。務必明確指定編碼方式(UTF-8 幾乎永遠是正確選擇),並在將結果視為字串前,先解碼回位元組。

關於大小的意外。 Base64 會使酬載大小增加 33%。對於小型資源來說,這無關緊要。但對於嵌入在 JSON 中的 10 MB 檔案,影響就大了——你將在網路上傳輸 13.3 MB。對於較大的檔案,建議使用多部分上傳。

將其視為機密。值得說兩次:Base64不是加密。不要將密碼、API金鑰或其他敏感資料存儲為Base64,期望它被隱藏。如果你能看到編碼後的字串,你就能看到原始內容。


我是William,DevCrate的開發者。Base64工具 的存在是因為我厭倦了將偽隨機字串丟進可疑的線上轉換器來查看內容。它能編碼和解碼標準及 URL-safe 兩種變體,處理檔案,且不會將任何一個位元組送出你的機器。

如果本指南沒有涵蓋某個 Base64 情況,請在留言中提出——我會仔細閱讀每一則。