<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Safety on 技術、遊戲、生活通俗易懂的解釋</title><link>https://takao.blog/zh-tw/tags/safety/</link><description>Recent content in Safety on 技術、遊戲、生活通俗易懂的解釋</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><copyright>Commentary of Takao</copyright><lastBuildDate>Thu, 25 Jun 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://takao.blog/zh-tw/tags/safety/index.xml" rel="self" type="application/rss+xml"/><item><title>OWASP ZAP in 2026: 進階 Scanning and CI/CD Integration</title><link>https://takao.blog/zh-tw/web/owasp-zap-advanced-2026/</link><pubDate>Tue, 09 Jun 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/owasp-zap-advanced-2026/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/owasp-zap-advanced-2026-zh-tw.png" alt="Featured image of post OWASP ZAP in 2026: 進階 Scanning and CI/CD Integration" /&gt;&lt;h2 id="beyond-basic-scanning"&gt;Beyond Basic Scanning
&lt;/h2&gt;&lt;p&gt;OWASP ZAP has evolved significantly since its early days. In 2026, it is no longer just a point-and-click proxy scanner — it is a full-featured security automation platform with a powerful API, a scriptable automation framework, and deep CI/CD integration. If you need the basics first, read our &lt;a class="link" href="https://takao.blog/web/how-to-owasp-zap/" &gt;OWASP ZAP installation and setup guide&lt;/a&gt;. This article covers advanced workflows for teams running security tests at scale.&lt;/p&gt;
&lt;h2 id="api-scanning-with-zap"&gt;API Scanning with ZAP
&lt;/h2&gt;&lt;p&gt;Modern applications rely heavily on REST and GraphQL APIs. ZAP&amp;rsquo;s OpenAPI and GraphQL 支援 allows you to scan APIs without a browser.&lt;/p&gt;</description></item><item><title>為 Hugo 部落格設計現代內容安全策略</title><link>https://takao.blog/zh-tw/web/hugo-latest-csp-best-practices-2026/</link><pubDate>Fri, 05 Jun 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/hugo-latest-csp-best-practices-2026/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/hugo-latest-csp-best-practices-2026-zh-tw.png" alt="Featured image of post 為 Hugo 部落格設計現代內容安全策略" /&gt;&lt;h2 id="為什麼-csp-對於靜態網站很重要"&gt;為什麼 CSP 對於靜態網站很重要
&lt;/h2&gt;&lt;p&gt;使用 Hugo 建立的靜態網站本質上比動態應用程式更安全，但它們仍然執行用於分析、廣告和嵌入的第三方腳本。 &lt;strong&gt;內容安全策略 (CSP)&lt;/strong&gt; 透過控制可以載入的資源來保護您的訪客免受 XSS、資料注入和惡意腳本執行的侵害。&lt;/p&gt;
&lt;h2 id="透過-cloudflare-pages-設定-csp"&gt;透過 Cloudflare Pages 設定 CSP
&lt;/h2&gt;&lt;p&gt;Cloudflare Pages 支援自訂 &lt;code&gt;_headers&lt;/code&gt; 檔案來控制 HTTP 回應標頭：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# static/_headers
/*
 Content-Security-Policy: default-src &amp;#39;self&amp;#39;; script-src &amp;#39;self&amp;#39;; style-src &amp;#39;self&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;對於 Hugo，將 &lt;code&gt;_headers&lt;/code&gt; 檔案放在 &lt;code&gt;static/&lt;/code&gt; 目錄中，以便將其複製到輸出：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;static/
├── _headers
├── css/
└── js/
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="為-hugo-建構現實的-csp"&gt;為 Hugo 建構現實的 CSP
&lt;/h2&gt;&lt;p&gt;使用 Google AdSense、Google Analytics 和嵌入式 YouTube 影片的部落格需要更寬鬆的政策。這是一個生產就緒的 CSP：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# static/_headers
/*
 Content-Security-Policy:
 default-src &amp;#39;self&amp;#39;;
 script-src &amp;#39;self&amp;#39;
 &amp;#39;strict-dynamic&amp;#39;
 &amp;#39;sha256-...&amp;#39; (inline script hash)
 https://www.googletagmanager.com
 https://pagead2.googlesyndication.com
 https://www.youtube.com;
 style-src &amp;#39;self&amp;#39;
 &amp;#39;sha256-...&amp;#39; (inline style hash)
 https://fonts.googleapis.com;
 img-src &amp;#39;self&amp;#39;
 https://*.googleapis.com
 https://*.googlesyndication.com
 https://www.google.com
 https://*.doubleclick.net
 https://*.youtube.com
 data:;
 font-src &amp;#39;self&amp;#39;
 https://fonts.gstatic.com;
 frame-src &amp;#39;self&amp;#39;
 https://www.youtube.com
 https://www.google.com;
 connect-src &amp;#39;self&amp;#39;
 https://*.google-analytics.com;
 report-uri /csp-report;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="使用隨機數與哈希值"&gt;使用隨機數與哈希值
&lt;/h2&gt;&lt;p&gt;對於內嵌腳本（在 Hugo 主題中常見），您有兩個選項：&lt;/p&gt;</description></item><item><title>使用 SSH 金鑰代替 GPG 金鑰進行 Git 提交簽名</title><link>https://takao.blog/zh-tw/web/git-signing-commits-ssh-keys/</link><pubDate>Mon, 25 May 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/git-signing-commits-ssh-keys/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/git-signing-commits-ssh-keys-zh-tw.png" alt="Featured image of post 使用 SSH 金鑰代替 GPG 金鑰進行 Git 提交簽名" /&gt;&lt;p&gt;長期以來，GPG（GNU Privacy Guard）金鑰是簽署 Git 提交以證明身份並防止篡改的行業標準。然而，設定 GPG 涉及產生密鑰環、管理過期日期和調試後台代理，這給開發人員帶來了很大的麻煩。&lt;/p&gt;
&lt;p&gt;為了消除這種複雜性，Git 2.34 版本引入了&lt;strong&gt;使用現有 SSH 金鑰直接簽署提交&lt;/strong&gt;的功能，從而繞過了 GPG 金鑰的需要。&lt;/p&gt;
&lt;p&gt;在本指南中，我們將探索如何設定 Git 以使用 SSH 金鑰來簽署提交、在本機驗證金鑰以及啟用跨開發團隊的信任關係。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-為什麼從-gpg-切換到-ssh-金鑰"&gt;1. 為什麼從 GPG 切換到 SSH 金鑰？
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;無金鑰冗餘&lt;/strong&gt;：您可以重複使用已用於透過 GitHub 進行驗證的相同 SSH 金鑰（例如 &lt;code&gt;id_ed25519&lt;/code&gt;），讓您無需產生和維護單獨的 GPG 金鑰對。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更簡單的設定&lt;/strong&gt;：只需要幾個終端命令即可運作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更乾淨的備份&lt;/strong&gt;：標準 SSH 金鑰重量輕，易於遷移，並且受到現代終端 shell 的原生支援。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="2-設定-git-使用-ssh-金鑰簽名"&gt;2. 設定 Git 使用 SSH 金鑰簽名
&lt;/h2&gt;&lt;h3 id="第-1-步將加密格式設定為-ssh"&gt;第 1 步：將加密格式設定為 SSH
&lt;/h3&gt;&lt;p&gt;告訴 Git 使用 SSH 而不是 GPG 進行提交簽名：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config --global gpg.format ssh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="第-2-步關聯您的-ssh-公鑰"&gt;第 2 步：關聯您的 SSH 公鑰
&lt;/h3&gt;&lt;p&gt;將 Git 指向您的 SSH 公鑰檔案（通常位於 &lt;code&gt;~/.ssh&lt;/code&gt; 目錄中的 &lt;code&gt;id_ed25519.pub&lt;/code&gt; 或 &lt;code&gt;id_rsa.pub&lt;/code&gt;）：&lt;/p&gt;</description></item><item><title>Testing CSP 規矩 Safely with Content-Security-Policy-Report-Only</title><link>https://takao.blog/zh-tw/web/security-content-security-policy-csp-report-only/</link><pubDate>Fri, 15 May 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-content-security-policy-csp-report-only/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-content-security-policy-csp-report-only-zh-tw.png" alt="Featured image of post Testing CSP 規矩 Safely with Content-Security-Policy-Report-Only" /&gt;&lt;h2 id="the-broken-widget-problem"&gt;The Broken-Widget Problem
&lt;/h2&gt;&lt;p&gt;Deploying a Content Security Policy is one of the strongest defenses against XSS attacks. But a single misconfigured directive can silently break inline scripts, block CDN resources, or disable analytics. If you apply CSP directly via the &lt;code&gt;Content-Security-Policy&lt;/code&gt; header and a critical script gets blocked, your production site breaks—often without an obvious error console notification.&lt;/p&gt;
&lt;p&gt;This is where &lt;strong&gt;Report-Only mode&lt;/strong&gt; saves the day.&lt;/p&gt;
&lt;h2 id="report-only-vs-enforced-mode"&gt;Report-Only vs Enforced Mode
&lt;/h2&gt;&lt;p&gt;CSP supports two headers:&lt;/p&gt;</description></item><item><title>網路安全中 JWT 令牌與有狀態會話的比較</title><link>https://takao.blog/zh-tw/web/security-jwt-vs-session-auth/</link><pubDate>Fri, 20 Mar 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-jwt-vs-session-auth/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-jwt-vs-session-auth-zh-tw.png" alt="Featured image of post 網路安全中 JWT 令牌與有狀態會話的比較" /&gt;&lt;h2 id="介紹"&gt;介紹
&lt;/h2&gt;&lt;p&gt;身份驗證是每個 Web 應用程式的支柱。出現了兩種主要模式：&lt;strong&gt;無狀態 JWT（JSON Web 令牌）&lt;/strong&gt; 身份驗證和 &lt;strong&gt;基於狀態會話&lt;/strong&gt; 身份驗證。兩者都解決相同的問題——在後續請求中驗證用戶是誰——但它們在儲存、撤銷和安全屬性方面有根本的不同。本文提供了詳細的比較，以幫助您選擇適合您的應用程式的方法。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="智威湯遜結構"&gt;智威湯遜結構
&lt;/h2&gt;&lt;p&gt;JWT 是一個獨立的令牌，由三個以點分隔的 base64url 編碼段組成：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;header.payload.signature
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;// Header
{
 &amp;#34;alg&amp;#34;: &amp;#34;HS256&amp;#34;,
 &amp;#34;typ&amp;#34;: &amp;#34;JWT&amp;#34;
}
// Payload
{
 &amp;#34;sub&amp;#34;: &amp;#34;user123&amp;#34;,
 &amp;#34;iat&amp;#34;: 1712345678,
 &amp;#34;exp&amp;#34;: 1712349278,
 &amp;#34;role&amp;#34;: &amp;#34;admin&amp;#34;
}
// Signature (HMAC-SHA256 of header + payload)
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;細分&lt;/th&gt;
					&lt;th&gt;內容&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;標題&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;演算法（&lt;code&gt;HS256&lt;/code&gt;、&lt;code&gt;RS256&lt;/code&gt;）與令牌類型&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;有效負載&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;宣告 — &lt;code&gt;sub&lt;/code&gt;（主題）、&lt;code&gt;iat&lt;/code&gt;（發佈於）、&lt;code&gt;exp&lt;/code&gt;（過期）、自訂資料&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;簽名&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;驗證令牌未被竄改&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;由於有效負載僅採用 Base64 編碼（未加密），因此&lt;strong&gt;敏感資料絕不能放置在有效負載中&lt;/strong&gt;，除非使用 JWE（JSON Web 加密）。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="基於會話的身份驗證"&gt;基於會話的身份驗證
&lt;/h2&gt;&lt;p&gt;在基於會話的身份驗證中，伺服器儲存會話資料（通常在記憶體、Redis 或資料庫中）。客戶端僅在 cookie 中保存會話 ID（隨機的不透明字串）：&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;sequenceDiagram
 Client-&gt;&gt;Server: POST /login (credentials)
 Server-&gt;&gt;Server: Create session (store user data)
 Server-&gt;&gt;Client: Set-Cookie: session_id=random_hash
 Client-&gt;&gt;Server: GET /protected (Cookie)
 Server-&gt;&gt;Server: Look up session in store
 Server-&gt;&gt;Client: 200 OK (response)&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="頭對頭比較"&gt;頭對頭比較
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方面&lt;/th&gt;
					&lt;th&gt;智威湯遜&lt;/th&gt;
					&lt;th&gt;會議&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;儲存位置&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;客戶端持有所有資料&lt;/td&gt;
					&lt;td&gt;伺服器保存會話資料&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;伺服器狀態&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;無狀態 — 無需資料庫查找&lt;/td&gt;
					&lt;td&gt;有狀態 — 需要會話儲存查詢&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;可擴充性&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;非常好 - 沒有共用會話儲存&lt;/td&gt;
					&lt;td&gt;多實例需要集中式Redis/DB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;撤銷&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;困難 — 有效期限至 &lt;code&gt;exp&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;立即 — 從儲存中刪除會話&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;代幣大小&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;更大（數百位元組）&lt;/td&gt;
					&lt;td&gt;小（會話 ID ~32 位元組）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;XSS 漏洞&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;JS (localStorage) 可存取的令牌&lt;/td&gt;
					&lt;td&gt;JS 無法存取 httpOnly cookie&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;CSRF 保護&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;需要人工處理&lt;/td&gt;
					&lt;td&gt;SameSite cookie + CSRF 令牌&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="jwt-的撤銷挑戰"&gt;JWT 的撤銷挑戰
&lt;/h2&gt;&lt;p&gt;JWT 最顯著的弱點是&lt;strong&gt;撤銷&lt;/strong&gt;。一旦發出，JWT 將保持有效，直到其 &lt;code&gt;exp&lt;/code&gt; 聲明為止。如果使用者登出、更改密碼或被禁止，則在沒有伺服器端狀態的情況下令牌無法失效，這違反了無狀態前提。&lt;/p&gt;</description></item><item><title>域安全性：設定 SPF、DKIM 和 DMARC 設定</title><link>https://takao.blog/zh-tw/web/web-security-dnssec-spf-dkim-dmarc/</link><pubDate>Sun, 15 Feb 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/web-security-dnssec-spf-dkim-dmarc/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/web-security-dnssec-spf-dkim-dmarc-zh-tw.png" alt="Featured image of post 域安全性：設定 SPF、DKIM 和 DMARC 設定" /&gt;&lt;h2 id="介紹"&gt;介紹
&lt;/h2&gt;&lt;p&gt;電子郵件驗證對於防止網域欺騙、網路釣魚和垃圾郵件資料夾拒絕至關重要。三個基於 DNS 的標準 — &lt;strong&gt;SPF&lt;/strong&gt;、&lt;strong&gt;DKIM&lt;/strong&gt; 和 &lt;strong&gt;DMARC&lt;/strong&gt; — 共同驗證聲稱來自您的網域的電子郵件是否合法。如果沒有這些記錄，攻擊者就可以代表您發送偽造的電子郵件，而合法電子郵件可能會進入收件者的垃圾郵件資料夾。本指南解釋了每個標準並展示如何在 Cloudflare 或您的 DNS 提供者上配置它們。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="spf寄件者策略框架"&gt;SPF：寄件者策略框架
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;SPF&lt;/strong&gt; 發布授權為您的網域發送電子郵件的 IP 位址清單。收件者郵件伺服器根據 SPF 記錄檢查 &lt;code&gt;Return-Path&lt;/code&gt; 網域。&lt;/p&gt;
&lt;h3 id="spf-記錄格式"&gt;SPF 記錄格式
&lt;/h3&gt;&lt;p&gt;SPF 記錄是 DNS &lt;strong&gt;TXT&lt;/strong&gt; 記錄：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;example.com TXT &amp;#34;v=spf1 include:_spf.google.com include:spf.mailgun.org ~all&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;機制&lt;/th&gt;
					&lt;th&gt;意義&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;SPF 版本標識符&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;將授權委託給另一個域&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ip4:&lt;/code&gt;/&lt;code&gt;ip6:&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;授權特定 IP 範圍&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;授權網域的A記錄&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;授權網域的 MX 伺服器&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不符合寄件者的預設操作&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="預選賽"&gt;預選賽
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;預選賽&lt;/th&gt;
					&lt;th&gt;行動&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;通過（預設）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;SoftFail（已標記但已接受）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;失敗（應該被拒絕）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;中立（無斷言）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在初始設定期間使用 &lt;code&gt;~all&lt;/code&gt;，然後在驗證後遷移到 &lt;code&gt;-all&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>使用HSTS策略安全地實施HTTPS連接</title><link>https://takao.blog/zh-tw/web/web-security-http-strict-transport-hsts-hacks/</link><pubDate>Fri, 16 Jan 2026 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/web-security-http-strict-transport-hsts-hacks/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/web-security-http-strict-transport-hsts-hacks-zh-tw.png" alt="Featured image of post 使用HSTS策略安全地實施HTTPS連接" /&gt;&lt;h2 id="第一個請求問題"&gt;第一個請求問題
&lt;/h2&gt;&lt;p&gt;HTTPS 在建立連線後對流量進行加密，但對 HTTP URL 的初始請求仍以明文形式傳送。同網路上的攻擊者可以攔截第一個請求，執行 &lt;strong&gt;SSL 分割&lt;/strong&gt;攻擊，將使用者在整個會話中降級為 HTTP。&lt;/p&gt;
&lt;p&gt;HTTP 嚴格傳輸安全性 (HSTS) 會關閉此視窗。一旦瀏覽器收到 HSTS 標頭，它就會&lt;strong&gt;自動將所有未來的 HTTP 請求&lt;/strong&gt;升級為 HTTPS，並在憑證無效時拒絕連線。&lt;/p&gt;
&lt;h2 id="hsts-的工作原理"&gt;HSTS 的工作原理
&lt;/h2&gt;&lt;p&gt;伺服器在 HTTPS 回應中傳送 &lt;code&gt;Strict-Transport-Security&lt;/code&gt; 標頭：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-http" data-lang="http"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;指令&lt;/th&gt;
					&lt;th&gt;描述&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;瀏覽器應記得只使用 HTTPS 多久&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;將政策套用至所有子域&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;瀏覽器預裝清單包含訊號&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;處理後，瀏覽器：
1.將網域的所有&lt;code&gt;http://&lt;/code&gt;連結改寫為&lt;code&gt;https://&lt;/code&gt;
2.如果TLS握手失敗或無效，則拒絕連接
3. 在 &lt;code&gt;max-age&lt;/code&gt; 的持續時段緩存策略&lt;/p&gt;
&lt;h2 id="在伺服器上設定-hsts"&gt;在伺服器上設定 HSTS
&lt;/h2&gt;&lt;h3 id="nginx"&gt;NGINX
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listen&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ssl&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_certificate&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/ssl/certs/example.pem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_certificate_key&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/ssl/private/example.key&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;add_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Strict-Transport-Security&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;max-age=63072000&lt;/span&gt;; &lt;span style="color:#f92672"&gt;includeSubDomains&lt;/span&gt;; &lt;span style="color:#f92672"&gt;preload&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;always&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;即使在錯誤頁面上染色體傳送標頭，「始終」參數也能確保。&lt;/p&gt;
&lt;p&gt;###阿帕契&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-apache" data-lang="apache"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Header always set Strict-Transport-Security &lt;span style="color:#e6db74"&gt;&amp;#34;max-age=31536000; includeSubDomains&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;###雲耀&lt;/p&gt;
&lt;p&gt;Cloudflare 穿透儀表板實現 HSTS：&lt;strong&gt;SSL/TLS &amp;gt; 邊緣權限 &amp;gt; HTTP 嚴格傳輸安全性&lt;/strong&gt;。您可以一鍵切換預先載入和 &lt;code&gt;includeSubDomains&lt;/code&gt;。 Cloudflare 也提供 &lt;strong&gt;「No Sniff」&lt;/strong&gt; 模式，可防止邊緣的降級攻擊。&lt;/p&gt;</description></item><item><title>CORS的工作原理以及修復訪問阻止錯誤</title><link>https://takao.blog/zh-tw/web/web-security-http-headers-cors/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/web-security-http-headers-cors/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/web-security-http-headers-cors-zh-tw.png" alt="Featured image of post CORS的工作原理以及修復訪問阻止錯誤" /&gt;&lt;h2 id="介紹"&gt;介紹
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;CORS（來源資源共享）&lt;strong&gt;是一種瀏覽器安全，用於控制來自一個來源的網頁機制如何請求來自不同來源的資源。當&lt;code&gt;https://app.example.com&lt;/code&gt;處的前端嘗試從&lt;code&gt;https://api.example.org&lt;/code&gt;取得資料時，瀏覽器預設強制執行&lt;/strong&gt;同源策略&lt;/strong&gt;。 CORS提供了一種突破HTTP標頭來放寬此策略的受控方法。本文介紹了完整的CORS流程、預檢請求以及如何修復常見的跨存取阻止錯誤。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="同源政策"&gt;同源政策
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;起源&lt;/strong&gt;由&lt;strong&gt;方案&lt;/strong&gt;、&lt;strong&gt;主機&lt;/strong&gt;和&lt;strong&gt;連接埠&lt;/strong&gt;的組合定義：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;網址&lt;/th&gt;
					&lt;th&gt;產地&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_1&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;同源&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不同產地（不同方案）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不同來源（不同主機）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不同產地（不同口岸）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;預設情況下，同源策略將阻止讀取跨來源回應。這可以防止惡意網站竊取其他來源的資料。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="簡單請求與預檢請求"&gt;簡單請求與預檢請求
&lt;/h2&gt;&lt;p&gt;CORS區分&lt;strong&gt;簡單請求&lt;/strong&gt;和觸發&lt;strong&gt;預檢&lt;/strong&gt;的請求。&lt;/p&gt;
&lt;p&gt;如果滿足所有這些條件，請求就是&lt;strong&gt;簡單&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;方法：&lt;code&gt;GET&lt;/code&gt;、&lt;code&gt;HEAD&lt;/code&gt; 或 &lt;code&gt;POST&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;內容類型：&lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;、&lt;code&gt;multipart/form-data&lt;/code&gt; 或 &lt;code&gt;text/plain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;沒有自訂標頭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;對於簡單請求，瀏覽器直接發送請求並檢查回應中的 CORS 標頭。&lt;/p&gt;
&lt;p&gt;所有其他請求都會觸發觸發&lt;strong&gt;預檢&lt;/strong&gt; — 實際上在發送的&lt;code&gt;OPTIONS&lt;/code&gt;請求之前：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;OPTIONS /api/data HTTP/1.1
Host: api.example.org
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;伺服器器必須使用適當的 CORS 標頭進行回應，瀏覽器才能繼續。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="核心-cors-回應標頭"&gt;核心 CORS 回應標頭
&lt;/h2&gt;&lt;p&gt;伺服器利用這些回應的標頭控制 CORS 行為：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;標題&lt;/th&gt;
					&lt;th&gt;目的&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位允許符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;指定哪些來源&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位允許符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;上線的 HTTP 方法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位允許符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;上市的自訂請求標頭&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位允許符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;是否權限（cookie）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;預檢結果可以緩存多久&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;回應的標頭是可存取的&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;預檢的 CORS 回應範例：&lt;/p&gt;</description></item><item><title>審核 NPM 依賴關係：Snyk 和自動化修補程式管理</title><link>https://takao.blog/zh-tw/web/security-dependency-vulnerabilities-npm-audit/</link><pubDate>Sat, 15 Nov 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-dependency-vulnerabilities-npm-audit/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-dependency-vulnerabilities-npm-audit-zh-tw.png" alt="Featured image of post 審核 NPM 依賴關係：Snyk 和自動化修補程式管理" /&gt;&lt;h2 id="供應鏈問題"&gt;供應鏈問題
&lt;/h2&gt;&lt;p&gt;現代 JavaScript 應用程式提供了數以萬計的傳遞依賴項。每一個都是潛在的攻擊媒介。 &lt;strong&gt;event-stream&lt;/strong&gt; 事件（2018 年）將惡意程式包注入到流行的依賴項中，這表示漏洞可能來自樹中的任何位置。在這種規模下，僅依靠人工審核是不可能的。&lt;/p&gt;
&lt;p&gt;自動化工具是唯一實用的防禦措施。&lt;/p&gt;
&lt;h2 id="新專案管理審計"&gt;新專案管理審計
&lt;/h2&gt;&lt;p&gt;內建 &lt;code&gt;npm audit&lt;/code&gt; 指令將您的依賴關係樹與已知漏洞的精選資料庫進行比較。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm audit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;輸出按嚴重性（嚴重、高、中、低）分組，包括易受攻擊的路徑、修補版本和 CVE 參考。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;┌───────────────┬────────────────────────────────────┐
│ critical │ Prototype Pollution in lodash │
├───────────────┼────────────────────────────────────┤
│ package │ lodash │
│ patched in │ &amp;gt;=4.17.21 │
│ dependency │ root → express → ... → lodash │
└───────────────┴────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm audit fix &lt;span style="color:#75715e"&gt;# auto-update to safe versions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm audit fix --force &lt;span style="color:#75715e"&gt;# allow breaking changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在應用之前使用 &lt;code&gt;--dry-run&lt;/code&gt; 預覽變更。&lt;/p&gt;
&lt;h3 id="限制"&gt;限制
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm audit&lt;/code&gt; 僅涵蓋 &lt;strong&gt;npm 註冊表諮詢資料庫&lt;/strong&gt;。它不會掃描所有 CVE 條目，只會掃描 npm 報告和接受的條目。&lt;/li&gt;
&lt;li&gt;對於那些從未在​​您的上下文中執行易受攻擊的程式碼路徑的框架，誤報很常見。&lt;/li&gt;
&lt;li&gt;該命令需要透過網路存取註冊表。離線審計需要本地諮詢鏡像。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="snyk更深層的選擇"&gt;Snyk：更深層的選擇
&lt;/h2&gt;&lt;p&gt;Snyk 不僅掃描 npm，還掃描 package-lock.json、yarn.lock、pnpm-lock.yaml、Docker 映像和 IaC 範本。它提供了更豐富的 CLI 和 GitHub/GitLab 整合。&lt;/p&gt;</description></item><item><title>使用 GPG 或 SSH 和驗證徽章簽署 Git 提交</title><link>https://takao.blog/zh-tw/web/git-commit-signing-gpg/</link><pubDate>Thu, 25 Sep 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/git-commit-signing-gpg/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/git-commit-signing-gpg-zh-tw.png" alt="Featured image of post 使用 GPG 或 SSH 和驗證徽章簽署 Git 提交" /&gt;&lt;p&gt;在 GitHub 上查看提交日誌時，您可能會注意到某些提交旁邊有一個綠色的「&lt;strong&gt;已驗證&lt;/strong&gt;」徽章。此標籤表示提交已加密簽名並確認來自合法的、經過驗證的使用者。&lt;/p&gt;
&lt;p&gt;預設情況下，Git 允許開發人員使用 &lt;code&gt;git config user.email&lt;/code&gt; 等簡單命令來配置他們選擇的任何名稱和電子郵件地址。這意味著冒充是微不足道的。為了確保身份驗證並防止未經授權的貢獻，強烈建議&lt;strong&gt;提交簽名&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在本指南中，我們將探索如何使用 GPG 或 SSH 金鑰設定 Git 提交簽名，以在 GitHub 上獲得您自己的「已驗證」徽章。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1什麼是提交簽名"&gt;1.什麼是提交簽名？
&lt;/h2&gt;&lt;p&gt;當您執行 git commit 命令時，提交簽章使用公鑰加密技術將數位簽章附加到提交資料。&lt;/p&gt;
&lt;p&gt;這保證了兩個關鍵的安全概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不可否認性&lt;/strong&gt;：驗證提交確實是由金鑰所有者創作的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;資料完整性&lt;/strong&gt;：確保自套用簽署以來提交元資料和檔案變更未被修改或篡改。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;雖然 GPG (GNU Privacy Guard) 金鑰歷來是唯一的選擇，但 Git 現在原生支援使用 &lt;strong&gt;SSH 金鑰&lt;/strong&gt; 進行提交簽名，這使得已經使用 SSH 金鑰推送程式碼的開發人員的設定變得更加簡單。在本指南中，我們將重點放在 SSH 金鑰簽署。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2-設定-ssh-金鑰提交簽名"&gt;2. 設定 SSH 金鑰提交簽名
&lt;/h2&gt;&lt;h3 id="第-1-步找到或產生-ssh-金鑰"&gt;第 1 步：找到或產生 SSH 金鑰
&lt;/h3&gt;&lt;p&gt;決定 SSH 公鑰的路徑（通常為 &lt;code&gt;~/.ssh/id_ed25519.pub&lt;/code&gt;）。如果您沒有，請使用以下命令產生它：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-keygen -t ed25519 -C &lt;span style="color:#e6db74"&gt;&amp;#34;your_email@example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="步驟-2設定-git-使用-ssh-進行簽名"&gt;步驟 2：設定 Git 使用 SSH 進行簽名
&lt;/h3&gt;&lt;p&gt;執行以下命令告訴 Git 使用您的 SSH 金鑰對提交進行簽名：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Instruct Git to use SSH as the cryptographic format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config --global gpg.format ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Point Git to your SSH public key file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git config --global user.signingkey ~/.ssh/id_ed25519.pub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="步驟-3啟用全域自動簽名"&gt;步驟 3：啟用全域自動簽名
&lt;/h3&gt;&lt;p&gt;為了避免在每次提交時手動輸入 &lt;code&gt;-S&lt;/code&gt; ，請將 Git 配置為自動簽署所有提交：&lt;/p&gt;</description></item><item><title>緩解 CSRF：SameSite Cookie 屬性和 CSRF 令牌</title><link>https://takao.blog/zh-tw/web/security-csrf-tokens-samesite-cookies/</link><pubDate>Mon, 25 Aug 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-csrf-tokens-samesite-cookies/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-csrf-tokens-samesite-cookies-zh-tw.png" alt="Featured image of post 緩解 CSRF：SameSite Cookie 屬性和 CSRF 令牌" /&gt;&lt;h2 id="介紹"&gt;介紹
&lt;/h2&gt;&lt;p&gt;Cookie 是管理使用者驗證狀態的便利機制。當會話 ID 儲存在 cookie 中時，瀏覽器會自動將其附加到針對該網域的傳出 HTTP 請求。&lt;/p&gt;
&lt;p&gt;但是，此自動附件功能會被 &lt;strong&gt;跨站點請求偽造 (CSRF)&lt;/strong&gt; 攻擊所利用。&lt;/p&gt;
&lt;p&gt;儘管現代瀏覽器預設採用更安全的 cookie 行為（例如自動套用 &lt;code&gt;SameSite=Lax&lt;/code&gt;），但開發人員必須了解 CSRF 防禦模式以防止嚴重的驗證漏洞。本文回顧 SameSite cookie 屬性和 CSRF 令牌驗證模式。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-csrf-攻擊如何運作"&gt;1. CSRF 攻擊如何運作
&lt;/h2&gt;&lt;p&gt;當惡意網站提示受害者的瀏覽器&lt;strong&gt;在使用者目前經過驗證的受信任應用程式上執行不需要的操作&lt;/strong&gt;時，就會發生 CSRF 攻擊。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用者登入銀行應用程式 (&lt;code&gt;bank.com&lt;/code&gt;)，伺服器將會話識別碼儲存在本機 cookie 中。&lt;/li&gt;
&lt;li&gt;經過身份驗證後，使用者造訪惡意網站 (&lt;code&gt;evil.com&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;惡意網站執行一個腳本，將轉帳請求 (&lt;code&gt;POST /transfer&lt;/code&gt;) 傳送到銀行應用程式 (&lt;code&gt;bank.com&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;由於請求的目標是 &lt;code&gt;bank.com&lt;/code&gt;，瀏覽器會自動包含經過驗證的會話 cookie。&lt;/li&gt;
&lt;li&gt;銀行伺服器將請求作為合法的、經過身份驗證的會話處理，並執行交易。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="2防禦一samesite-cookie-屬性"&gt;2.防禦一：SameSite Cookie 屬性
&lt;/h2&gt;&lt;p&gt;防止 CSRF 最有效的方法是將 &lt;strong&gt;&lt;code&gt;SameSite&lt;/code&gt;&lt;/strong&gt; 屬性套用至會話 cookie。此設定告訴瀏覽器是否應將 cookie 包含在源自第三方（跨網站）網域的請求中。&lt;/p&gt;
&lt;h3 id="三種配置選項"&gt;三種配置選項
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-http" data-lang="http"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Lax
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: left"&gt;設定&lt;/th&gt;
					&lt;th style="text-align: left"&gt;行為&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;SameSite=嚴格&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;阻止瀏覽器在跨網站請求中傳送 cookie。即使用戶從外部搜尋引擎點擊直接連結到您的網站，他們也需要再次登錄，因為 cookie 已保留。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;SameSite=寬鬆&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;在跨網站請求上保留 cookie，但在使用者透過點擊連結（GET 請求）導航到您的網站時允許 cookie。這是 Web 應用程式的行業預設設定。&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;SameSite=無&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;將 cookie 附加到所有跨站點請求，包括嵌入式 iframe 呼叫。設定 &lt;code&gt;SameSite=None&lt;/code&gt; 需要 &lt;code&gt;Secure&lt;/code&gt; 標誌（限制傳輸到 HTTPS 連線）。&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="samesitelax-的重要限制"&gt;SameSite=Lax 的重要限制
&lt;/h3&gt;&lt;p&gt;雖然大多數現代瀏覽器預設使用 &lt;code&gt;SameSite=Lax&lt;/code&gt;，但僅依賴它會留下潛在的安全漏洞：&lt;/p&gt;</description></item><item><title>Why and 如何 Adopt 'strict-dynamic' in CSP</title><link>https://takao.blog/zh-tw/web/security-csp-strict-dynamic-implementation/</link><pubDate>Sun, 15 Jun 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-csp-strict-dynamic-implementation/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-csp-strict-dynamic-implementation-zh-tw.png" alt="Featured image of post Why and 如何 Adopt 'strict-dynamic' in CSP" /&gt;&lt;h2 id="introduction"&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Implementing a &lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt; is a highly effective way to mitigate Cross-Site Scripting (XSS) risks. However, configuring and maintaining the policy can become a major headache.&lt;/p&gt;
&lt;p&gt;For websites utilizing third-party SDKs (such as Google Tag Manager, analytics beacons, 支付 widgets, or social sharing buttons), these scripts often dynamically load (inject) additional scripts from nested domains. This forces developers to maintain a long, fragile whitelist of external domains in the &lt;code&gt;script-src&lt;/code&gt; directive.&lt;/p&gt;</description></item><item><title>Web開發中XSS的防禦原則</title><link>https://takao.blog/zh-tw/web/security-basics-xss-prevention/</link><pubDate>Tue, 25 Feb 2025 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/security-basics-xss-prevention/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/security-basics-xss-prevention-zh-tw.png" alt="Featured image of post Web開發中XSS的防禦原則" /&gt;&lt;h2 id="介紹"&gt;介紹
&lt;/h2&gt;&lt;p&gt;在網路安全中，&lt;strong&gt;跨站腳本 (XSS)&lt;/strong&gt; 是最古老、最持久的漏洞之一。&lt;/p&gt;
&lt;p&gt;如果惡意腳本在受害者的瀏覽器上執行，它們可能會破壞整個會話、竊取會話令牌 (cookie)、劫持帳戶或動態變更頁面內容以取得敏感憑證。&lt;/p&gt;
&lt;p&gt;本文回顧了消除現代 Web 應用程式中 XSS 漏洞所需的基本防禦原則。我們將探索上下文轉義、清理、安全 DOM 操作和防禦深度機制。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1xss的三種分類"&gt;1.XSS的三種分類
&lt;/h2&gt;&lt;p&gt;根據惡意負載的傳輸方式，XSS 漏洞大致分為三類：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;反射的XSS：&lt;/strong&gt;
當惡意負載嵌入到連結或表單提交時會發生。當使用者點擊連結時，伺服器會將不受信任的輸入「反射」迴響應 HTML，而無需進行適當的轉義。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;儲存（持久）XSS：&lt;/strong&gt;
最危險的形式。有效負載儲存在伺服器的資料庫中（例如，論壇貼文、使用者簡介）並傳遞給任何存取該頁面的後續使用者。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基於 DOM 的 XSS：&lt;/strong&gt;
與反射或儲存 XSS 不同，這完全發生在客戶端 JavaScript 中。此腳本處理不受信任的來源資料（例如 &lt;code&gt;location.hash&lt;/code&gt; 或查詢參數）並使用不安全的 API 將其直接寫入 DOM。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="2-原則-1上下文感知-html-轉義"&gt;2. 原則 1：上下文感知 HTML 轉義
&lt;/h2&gt;&lt;p&gt;XSS 的根本解決方法是在渲染不受信任的動態資料之前對其進行轉義。轉義將 HTML 語法中具有特殊意義的字元文字轉換為各自的惰性 HTML 實體（字元引用）。&lt;/p&gt;
&lt;h3 id="基本字元映射表"&gt;基本字元映射表
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; -&amp;gt; &lt;code&gt;&amp;amp;amp;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; -&amp;gt; &lt;code&gt;&amp;amp;lt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;&amp;amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;quot;&lt;/code&gt; -&amp;gt; &lt;code&gt;&amp;amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'&lt;/code&gt; -&amp;gt; &lt;code&gt;&amp;amp;#x27;&lt;/code&gt; （或 &lt;code&gt;&amp;amp;apos;&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="警告上下文很重要"&gt;警告：上下文很重要
&lt;/h3&gt;&lt;p&gt;轉義規則會根據資料放置的「位置」而變化。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;放置在元素標記內的文字需要標準實體轉義。&lt;/li&gt;
&lt;li&gt;放置在元素屬性內的文字（例如 &lt;code&gt;&amp;lt;input value=&amp;quot;DYNAMIC_DATA&amp;quot;&amp;gt;&lt;/code&gt;）需要嚴格的引號轉義。&lt;/li&gt;
&lt;li&gt;單獨使用 HTML 轉義無法保護 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 區塊、CSS 版面配置或 URL 屬性 (&lt;code&gt;href&lt;/code&gt;) 內呈現的資料。它們分別需要 JavaScript 轉義、CSS 轉義或 URL 編碼。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="3-原則-2安全-dom-api防止基於-dom-的-xss"&gt;3. 原則 2：安全 DOM API（防止基於 DOM 的 XSS）
&lt;/h2&gt;&lt;p&gt;使用 JavaScript 動態更新頁面內容時，選擇錯誤的 API 可能會造成安全漏洞。&lt;/p&gt;</description></item><item><title>子資源完整性：保護您的 CDN 依賴項</title><link>https://takao.blog/zh-tw/web/subresource-integrity/</link><pubDate>Fri, 20 Dec 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/subresource-integrity/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/subresource-integrity-zh-tw.png" alt="Featured image of post 子資源完整性：保護您的 CDN 依賴項" /&gt;&lt;p&gt;子資源完整性 (SRI) 是一項安全功能，可讓瀏覽器驗證從 CDN 或第三方來源取得的資源是否未被竄改。在供應鏈攻擊的時代——英國航空 Magecart 漏洞、Polyfill.io 洩漏以及眾多 CDN 事件——SRI 提供加密保證，確保您的頁面加載的資源正是您想要的。&lt;/p&gt;
&lt;h2 id="社會責任投資如何運作"&gt;社會責任投資如何運作
&lt;/h2&gt;&lt;p&gt;當您將 &lt;code&gt;integrity&lt;/code&gt; 屬性新增至 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 或 &lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot;&amp;gt;&lt;/code&gt; 標記時，瀏覽器會計算所取得資源的雜湊值並與屬性值進行比較。如果它們不匹配，瀏覽器將拒絕執行或套用該資源。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.example.com/library.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;integrity&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;crossorigin&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;當資源的多個版本可接受時，多個雜湊（逗號分隔）允許優雅的回退：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.example.com/app.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;integrity&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;sha384-ABC... sha512-XYZ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;crossorigin&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;跨來源資源上的 SRI 需要 &lt;code&gt;crossorigin=&amp;quot;anonymous&amp;quot;&lt;/code&gt; 屬性。如果沒有正確的 CORS 標頭，瀏覽器會以不透明模式載入資源，並且無法驗證其完整性 - 此資源會被靜默忽略，不會出現任何錯誤。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="產生-sri-哈希值"&gt;產生 SRI 哈希值
&lt;/h2&gt;&lt;p&gt;您可以使用 OpenSSL、線上工具或建置時外掛程式產生 SRI 雜湊值：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# OpenSSL command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl dgst -sha384 -binary file.js | openssl base64 -A
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;為了實現自動化，請將 SRI 生成整合到您的建置管道中。建置工具支援已成熟：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;插件/配置&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;網頁包&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;佔位符_0&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;維特&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;vite-plugin-sri&lt;/code&gt; 或透過 &lt;code&gt;experimental.renderBuiltUrl&lt;/code&gt; 內建&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Next.js&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;next.config.js&lt;/code&gt; 中的 &lt;code&gt;experimental.sri&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;天文&lt;/td&gt;
					&lt;td&gt;資產組件上內建 &lt;code&gt;integrity&lt;/code&gt; 屬性&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Next.js SRI configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// next.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;exports&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;experimental&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sri&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;hash&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;sha384&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;確保在縮小和生成來源映射後計算哈希值 - 哈希值必須與最終提供的內容匹配，而不是與開發來源匹配。&lt;/p&gt;</description></item><item><title>Secure Cookie Configuration: A Complete Web Developer 指南</title><link>https://takao.blog/zh-tw/web/secure-cookies/</link><pubDate>Mon, 09 Dec 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/secure-cookies/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/secure-cookies-zh-tw.png" alt="Featured image of post Secure Cookie Configuration: A Complete Web Developer 指南" /&gt;&lt;p&gt;Cookies remain one of the most frequently misconfigured security controls on the web. A single missing attribute can expose your application to session hijacking, CSRF, or cross-site information leakage. Modern browsers have pushed stricter defaults, but understanding each attribute and combining them correctly is essential for defense-in-depth.&lt;/p&gt;
&lt;p&gt;The core security attributes are &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;SameSite&lt;/code&gt;, and the &lt;code&gt;__Host-&lt;/code&gt; / &lt;code&gt;__Secure-&lt;/code&gt; prefixes. Each serves a distinct purpose, and they work best when combined.&lt;/p&gt;</description></item><item><title>SQL Injection 預防: Modern Database Security 指南</title><link>https://takao.blog/zh-tw/web/sql-injection-prevention/</link><pubDate>Tue, 01 Oct 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/sql-injection-prevention/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/sql-injection-prevention-zh-tw.png" alt="Featured image of post SQL Injection 預防: Modern Database Security 指南" /&gt;&lt;p&gt;SQL injection remains in the OWASP Top 10 despite decades of awareness. The 2023-2024 period saw high-profile breaches in healthcare, e-commerce, and government sectors involving SQLi. While the classic &lt;code&gt;' OR 1=1 --&lt;/code&gt; attack is well-known, modern variants include second-order injection, blind SQLi (time-based and boolean-based), and out-of-band exfiltration. Prevention is well-understood but poorly executed due to legacy code, ORM misuse, and insufficient testing automation.&lt;/p&gt;
&lt;h2 id="parameterized-queries-and-prepared-statements"&gt;Parameterized Queries and Prepared Statements
&lt;/h2&gt;&lt;p&gt;Prepared statements are the gold standard for SQL injection prevention. They separate SQL logic from data at the database engine level, making it impossible for user input to alter query structure.&lt;/p&gt;</description></item><item><title>貨櫃安全掃描：保護您的供應鏈</title><link>https://takao.blog/zh-tw/web/container-security/</link><pubDate>Tue, 16 Jul 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/container-security/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/container-security-zh-tw.png" alt="Featured image of post 貨櫃安全掃描：保護您的供應鏈" /&gt;&lt;p&gt;容器安全不再是可選的。隨著供應鏈攻擊的增加，保護容器映像從建置到運行的整個過程是任何運行容器化工作負載的組織的基本要求。僅運行時安全是不夠的；供應鏈安全必須從形象建構階段開始。&lt;/p&gt;
&lt;h2 id="貨櫃供應鏈威脅格局"&gt;貨櫃供應鏈威脅格局
&lt;/h2&gt;&lt;p&gt;容器供應鏈中的攻擊媒介包括受損的基礎映像、易受攻擊的依賴項、洩漏的機密和惡意軟體包。 Codecov 洩漏憑證外洩、依賴性混淆攻擊以及公共影像中發現的加密貨幣挖礦程式等現實世界事件凸顯了這些威脅的嚴重性。共享責任模型意味著，雖然 Docker 等平台提供了基礎基礎設施，但建置映像的安全性是您的責任。&lt;/p&gt;
&lt;h2 id="鏡像漏洞掃描工具"&gt;鏡像漏洞掃描工具
&lt;/h2&gt;&lt;p&gt;有多種工具可用於掃描容器映像。 Aqua Security 的 Trivy 是開源的、快速且全面的，可以跨越 npm、pip、gem 和 Go 掃描作業系統套件和特定於語言的依賴項。 Snyk 提供一款商業掃描儀，具有開發人員友好的 CLI、PR 檢查和自動修復建議。 Anchore 的 Grype 與 Syft 整合以產生 SBOM，而 Docker Scout 則直接內建於 Docker Desktop 和 Docker Hub 中。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;類型&lt;/th&gt;
					&lt;th&gt;關鍵實力&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;瑣碎&lt;/td&gt;
					&lt;td&gt;開源&lt;/td&gt;
					&lt;td&gt;覆蓋速度與廣度&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;斯尼克&lt;/td&gt;
					&lt;td&gt;商業&lt;/td&gt;
					&lt;td&gt;修復建議和 PR 整合&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;格里普&lt;/td&gt;
					&lt;td&gt;開源&lt;/td&gt;
					&lt;td&gt;SBOM 與 Syft 整合&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Docker 偵察兵&lt;/td&gt;
					&lt;td&gt;內建&lt;/td&gt;
					&lt;td&gt;無縫 Docker 桌面整合&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="dockerfile-安全最佳實踐"&gt;Dockerfile 安全最佳實踐
&lt;/h2&gt;&lt;p&gt;最小基礎鏡像是安全容器的基礎。與完整作業系統映像相比，偏好 Alpine、distroless 或 scrap。多階段建置將建置依賴項與執行時間工件分開，讓您產生僅包含執行應用程式所需內容的最終映像。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;golang:1.22&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; &lt;span style="color:#e6db74"&gt;builder&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WORKDIR&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/app&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; go.mod go.sum ./&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; go mod download&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; . .&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; CGO_ENABLED&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; go build -o app .&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;alpine:3.20&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; addgroup -S appgroup &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; adduser -S appuser -G appgroup&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; --from&lt;span style="color:#f92672"&gt;=&lt;/span&gt;builder /app/app /app/app&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;USER&lt;/span&gt; &lt;span style="color:#e6db74"&gt;appuser&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;ENTRYPOINT&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#34;/app/app&amp;#34;&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;避免使用最新的標籤；固定到特定的摘要以進行可重現的建置。以非 root 使用者身分執行容器，刪除不必要的 Linux 功能，並將根檔案系統掛載為唯讀，並使用可寫入目錄的 tmpfs。&lt;/p&gt;</description></item><item><title>使用 Vaultwarden 和 Bitwarden SSH 代理程式管理 SSH 金鑰</title><link>https://takao.blog/zh-tw/web/vaultwarden-ssh-key/</link><pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate><guid>https://takao.blog/zh-tw/web/vaultwarden-ssh-key/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/vaultwarden-ssh-key-zh-tw.png" alt="Featured image of post 使用 Vaultwarden 和 Bitwarden SSH 代理程式管理 SSH 金鑰" /&gt;&lt;h2 id="為什麼將-ssh-金鑰儲存在密碼管理器中"&gt;為什麼將 SSH 金鑰儲存在密碼管理器中
&lt;/h2&gt;&lt;p&gt;SSH 金鑰是對遠端伺服器、Git 供應商和內部基礎架構進行身份驗證的黃金標準。然而，大多數開發人員將它們儲存為普通檔案在 &lt;code&gt;~/.ssh/&lt;/code&gt; 下 - 不受保護、未同步且未經審核。將 SSH 金鑰移至 Vaultwarden（或 Bitwarden）解決了三個基本問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;集中管理&lt;/strong&gt;：所有金鑰都位於一個保管庫中，而不是分散在各個電腦上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨裝置同步&lt;/strong&gt;：新增一次金鑰；它會自動出現在每個裝置上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;審計追蹤&lt;/strong&gt;：伺服器會記錄每個按鍵存取和用戶端操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bitwarden SSH 代理程式彌合了鎖定的保管庫和透明地使用 SSH 金鑰的日常需求之間的差距。&lt;/p&gt;
&lt;h2 id="bitwarden-ssh-代理程式概述"&gt;Bitwarden SSH 代理程式概述
&lt;/h2&gt;&lt;p&gt;Bitwarden SSH 代理程式是一個輕量級守護程序，它透過標準 &lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt; 介面公開儲存在保管庫中的 SSH 金鑰。當 &lt;code&gt;ssh&lt;/code&gt; 或 &lt;code&gt;git&lt;/code&gt; 需要金鑰時，它會與代理程式通信，代理請求 Bitwarden CLI (&lt;code&gt;bw&lt;/code&gt;) 從保管庫中取得對應的私鑰。金鑰材料永遠不會接觸磁碟 - 它位於加密的保管庫中，僅在需要時在記憶體中解密。&lt;/p&gt;
&lt;p&gt;此方法適用於任何 OpenSSH 相容客戶端：&lt;code&gt;ssh&lt;/code&gt;、&lt;code&gt;scp&lt;/code&gt;、&lt;code&gt;rsync&lt;/code&gt;、&lt;code&gt;git&lt;/code&gt;、&lt;code&gt;mosh&lt;/code&gt; 以及使用 SSH 代理協定的 GUI 工具。&lt;/p&gt;
&lt;h2 id="先決條件"&gt;先決條件
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;要求&lt;/th&gt;
					&lt;th&gt;筆記&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Vaultwarden 伺服器（自架）或 Bitwarden 雲端&lt;/td&gt;
					&lt;td&gt;CLI 登入需要 API 端點&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Bitwarden CLI (&lt;code&gt;bw&lt;/code&gt;)&lt;/td&gt;
					&lt;td&gt;官方命令列客戶端&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OpenSSH 用戶端&lt;/td&gt;
					&lt;td&gt;隨 Linux、macOS 和 Windows 10+ 一起提供&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt; 支援&lt;/td&gt;
					&lt;td&gt;各大平台皆可&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="安裝-bitwarden-cli"&gt;安裝 Bitwarden CLI
&lt;/h2&gt;&lt;h3 id="linux--macos"&gt;Linux / macOS
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Download the CLI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -Lo bw.zip &lt;span style="color:#e6db74"&gt;&amp;#34;https://vault.bitwarden.com/download/?app=cli&amp;amp;platform=linux&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unzip bw.zip
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo install bw /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rm bw.zip bw
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="windowspowershell"&gt;Windows（PowerShell）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Using winget&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;winget install Bitwarden.CLI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Or download manually&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Invoke-WebRequest -Uri &lt;span style="color:#e6db74"&gt;&amp;#34;https://vault.bitwarden.com/download/?app=cli&amp;amp;platform=windows&amp;#34;&lt;/span&gt; -OutFile bw.zip
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Expand-Archive -Path bw.zip -DestinationPath C:\tools\bw
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$env:Path += &lt;span style="color:#e6db74"&gt;&amp;#34;;C:\tools\bw&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;驗證安裝：&lt;/p&gt;</description></item><item><title>API 速率限制策略：保護您的服務</title><link>https://takao.blog/zh-tw/web/api-rate-limiting/</link><pubDate>Tue, 07 May 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/api-rate-limiting/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/api-rate-limiting-zh-tw.png" alt="Featured image of post API 速率限制策略：保護您的服務" /&gt;&lt;p&gt;速率限制是任何生產 API 的關鍵組成部分。它可以保護後端服務免遭濫用，確保公平的資源分配，保持負載下的效能，並減輕拒絕服務攻擊。本文研究了主要的速率限制演算法、它們的權衡以及設計穩健系統的最佳實踐。&lt;/p&gt;
&lt;h2 id="令牌桶演算法"&gt;令牌桶演算法
&lt;/h2&gt;&lt;p&gt;令牌桶是應用最廣泛的限速演算法之一。一個桶保存著以穩定速率重新填充的令牌，每個請求消耗一個令牌。如果桶子是空的，則請求被拒絕。這種方法允許突發達到桶容量，同時隨著時間的推移平滑流量。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TokenBucket&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;constructor&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;capacity&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;refillRate&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;capacity&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;capacity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tokens&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;capacity&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;refillRate&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;refillRate&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lastRefill&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Date.&lt;span style="color:#a6e22e"&gt;now&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;tryConsume&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;_refill&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tokens&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) { &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tokens&lt;/span&gt;&lt;span style="color:#f92672"&gt;--&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;_refill&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;now&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Date.&lt;span style="color:#a6e22e"&gt;now&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;elapsed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;now&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lastRefill&lt;/span&gt;) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tokens&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Math.&lt;span style="color:#a6e22e"&gt;min&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;capacity&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tokens&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;elapsed&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;refillRate&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;lastRefill&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;now&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;此實作簡單、記憶體效率高，每個客戶端只有一個計數器，非常適合需要突發容忍的通用速率限制。&lt;/p&gt;
&lt;h2 id="漏桶演算法"&gt;漏桶演算法
&lt;/h2&gt;&lt;p&gt;漏桶強制執行嚴格的流出率。請求進入隊列並以固定速率處理，完全防止突發。這使其成為保護無法處理突發流量峰值的下游系統的理想選擇。代價是由於佇列和無法處理任何類型的突發而導致更高的記憶體使用量。&lt;/p&gt;
&lt;h2 id="滑動視窗演算法"&gt;滑動視窗演算法
&lt;/h2&gt;&lt;p&gt;滑動視窗方法比固定視窗計數器提供更準確的速率限制。滑動視窗日誌儲存目前視窗內所有請求的時間戳記。對於每個請求，視窗外的條目都會被刪除，並檢查剩餘的計數。這種方法是基於視窗的方法中最準確的，但會佔用大量內存，因此適合低流量場景或精度至關重要的情況。&lt;/p&gt;
&lt;p&gt;滑動視窗計數器透過使用加權公式將先前的視窗計數與當前視窗部分計數相結合，提供了更實用的平衡：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;weightedCount = previousWindowCount * overlapRatio + currentWindowCount
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;此方法每個客戶端僅使用兩個計數器，為大多數用例提供良好的準確性，並且是 Stripe 和 GitHub 使用的行業標準。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="基於redis的實現"&gt;基於Redis的實現
&lt;/h2&gt;&lt;p&gt;Redis 是分散式速率限制最常見的後備儲存。其原子操作（例如 INCR 和 EXPIRE）提供了線程安全性，內建 TTL 可以實現自動計數器清理，Lua 腳本支援複雜的演算法實現。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;SlidingWindowRateLimiter&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;redis-rate-limiter&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;limiter&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SlidingWindowRateLimiter&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;client&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;redisClient&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; window&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;limit&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Redis 也為水平擴展和亞毫秒級操作延遲提供叢集支援。對於生產部署，用於原子速率限制、處理 Redis 故障轉移和效能調整的 Lua 腳本模式是重要的考慮因素。&lt;/p&gt;</description></item><item><title>WebAuthn and Passkeys: Passwordless 道地ation in 2024</title><link>https://takao.blog/zh-tw/web/webauthn-passkeys/</link><pubDate>Tue, 02 Apr 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/webauthn-passkeys/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/webauthn-passkeys-zh-tw.png" alt="Featured image of post WebAuthn and Passkeys: Passwordless 道地ation in 2024" /&gt;&lt;p&gt;Passwords have been the primary authentication mechanism for decades, but they come with well-documented security and usability problems. WebAuthn (Web Authentication) and the emerging passkey 生態系 promise to replace passwords with cryptographically secure, phishing-resistant authentication. As of 2024, passkey 支援 has reached critical mass across all major platforms, making this the ideal time to implement passwordless authentication.&lt;/p&gt;
&lt;h2 id="understanding-webauthn"&gt;Understanding WebAuthn
&lt;/h2&gt;&lt;p&gt;WebAuthn is a W3C standard that enables public-key cryptography-based authentication on the web. The core flow involves two operations: registration and authentication. During registration, the server sends a cryptographic challenge to the client, the authenticator creates a new key pair, and the public key is stored on the server. During authentication, the server sends a challenge, the authenticator signs it with the private key, and the server verifies the signature against the stored public key.&lt;/p&gt;</description></item><item><title>Vaultwarden: Self-Hosted Password Manager Installation 指南</title><link>https://takao.blog/zh-tw/web/vaultwarden-install/</link><pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate><guid>https://takao.blog/zh-tw/web/vaultwarden-install/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/vaultwarden-install-zh-tw.png" alt="Featured image of post Vaultwarden: Self-Hosted Password Manager Installation 指南" /&gt;&lt;h2 id="what-is-vaultwarden"&gt;What is Vaultwarden?
&lt;/h2&gt;&lt;p&gt;Vaultwarden is an open-source, self-hosted implementation of the Bitwarden server API, written in Rust. It is designed to be lightweight and resource-efficient compared to the official Bitwarden server, which requires a Microsoft SQL Server database and substantial system resources. Vaultwarden supports all official Bitwarden clients — desktop, browser extensions, mobile apps, and CLI — without any modification.&lt;/p&gt;
&lt;p&gt;By self-hosting Vaultwarden, you retain full control over your password data. No third-party service ever touches your encrypted vault. The project is mature, actively maintained, and suitable for both single-user deployments and small teams.&lt;/p&gt;</description></item><item><title>OAuth 2.0 and OpenID Connect: Modern 道地ation 指南</title><link>https://takao.blog/zh-tw/web/oauth-oidc/</link><pubDate>Mon, 29 Jan 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/oauth-oidc/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/oauth-oidc-zh-tw.png" alt="Featured image of post OAuth 2.0 and OpenID Connect: Modern 道地ation 指南" /&gt;&lt;p&gt;OAuth 2.0 and OpenID Connect form the backbone of modern web authentication and authorization. Despite their ubiquity, these protocols are frequently misunderstood and misconfigured, leading to preventable security vulnerabilities. This guide covers the core concepts, implementation patterns, and security best practices you need to integrate authentication securely in your applications.&lt;/p&gt;
&lt;h2 id="oauth-20-fundamentals"&gt;OAuth 2.0 Fundamentals
&lt;/h2&gt;&lt;p&gt;OAuth 2.0 is an authorization framework, not an authentication protocol. This distinction is critical: OAuth defines how a client application can obtain delegated access to protected resources, but it does not specify how to verify the user&amp;rsquo;s identity. That is where OpenID Connect comes in.&lt;/p&gt;</description></item></channel></rss>