跳至主要內容

自訂 Captive Portal:HTML 與 CSS 指南

本權威技術參考指南概述了設計和編寫自訂 Captive Portal 登入頁面所需的開發標準、CSS 架構和網路層級限制。它為前端開發人員和網路架構師提供了實用的策略,以應對 Apple CNA 和 Android webview 環境,確保提供像素級完美、合規且高效能的訪客 WiFi 體驗。

📖 11 分鐘閱讀📝 2,731 字數🔧 2 範例3 練習題📚 8 關鍵定義

收聽此指南

查看播客逐字稿
自訂 Captive Portal:HTML 與 CSS 指南 — Purple 技術簡報 [引言] 歡迎收看 Purple 技術簡報系列。今天我們將深入探討影響每個訪客 WiFi 部署的細節 — Captive Portal。具體來說,我們將討論如何為自訂 Captive Portal 登入頁面編寫乾淨、可靠的 HTML 和 CSS。 如果您曾經連接到酒店 WiFi,卻看到一個破裂的登入頁面 — 缺少圖片、未套用樣式的文字、對觸控沒有反應的登入按鈕 — 您就體驗過當開發人員在不了解其運作環境限制的情況下建置 portal 時會發生什麼事。今天,我們將確保這種情況不會發生在您身上。 本簡報針對前端開發人員、創意設計師和網頁開發人員,無論您是從頭開始建置 Captive Portal,還是自訂現有範本。我們將涵蓋 HTML 結構、重要的 CSS 規則、讓即使是有經驗的開發人員也感到棘手的 Apple CNA 微型瀏覽器限制,以及像 Purple 的 portal 產生器這樣的平台如何完全消除大部分的複雜性。 讓我們開始吧。 [技術深挖] 首先,讓我們在網路層級確立 Captive Portal 究竟是什麼。當裝置連接到需要驗證的 WiFi 網路時,網路會攔截 HTTP 流量並將使用者重新導向到登入頁面。這就是 Captive Portal。使用者會看到一個登入頁面,完成一項操作 — 輸入電子郵件、接受條款、透過社群媒體登入 — 然後網路就會授予完整的網際網路存取權限。 需要理解的關鍵是這個頁面是在哪裡渲染的。在 iOS 裝置上,它會在 Apple 的 Captive Network Assistant(即 CNA)中開啟,這是一個精簡版的 WebKit webview。它不是 Safari。它沒有持久性 Cookie。它無法載入外部資源。它的 JavaScript 支援有限。而且在使用者切換到另一個應用程式的瞬間,它就會關閉。在 macOS 上,CNA 以固定的 900 x 572 像素進行渲染。在 Android 上,現代裝置使用 Chrome Custom Tabs,其功能要強大得多。Windows 10 會開啟使用者的預設瀏覽器。Samsung 裝置則使用 Samsung Internet。 這種平台碎片化是生產環境中 Captive Portal 破裂的最大單一原因。開發人員在他們的 Android 手機上進行測試,一切看起來都很棒,然後酒店裡拿著 iPhone 的訪客卻看到一個帶有未套用樣式文字的空白畫面。因此,讓我們來談談如何進行防禦性編碼。 Captive Portal HTML 和 CSS 的黃金法則就是:將頁面視為沒有網際網路連線。因為在驗證階段,它確實沒有。網路是處於 captive 狀態的。您的頁面嘗試從外部 URL 載入的任何資源 — Google Font、CDN 託管的樣式表、JavaScript 程式庫、標誌圖片 — 都會靜默失敗,或導致載入圖示無限旋轉。 從 HTML 結構開始。您的文件應該是一個乾淨的 HTML5 頁面。在 head 中,您需要一個 viewport meta 標籤,其內容設定為 width 等於 device-width 且 initial-scale 等於 1。這對於行動裝置渲染是不可妥協的。如果沒有它,iOS 將以 980 像素寬度渲染頁面並將其縮小,使所有內容都變得極小。 您的 CSS 必須是內聯的 — 可以是 head 元素內 style 區塊中的樣式,也可以是個別元素上的內聯樣式屬性。請勿使用透過 link 標籤連結的外部樣式表。該樣式表存在於您的伺服器上,而 captive 網路在驗證期間無法存取該伺服器。頁面將會完全未套用樣式地渲染。 對於字型,請使用系統字型堆疊。例如:font-family — apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif。這會告訴瀏覽器使用任何可用的系統字型。請勿使用 Google Fonts。import 呼叫將會失敗,而您的備用字型將會是 Times New Roman,這並不是您的客戶付費想要獲得的品牌體驗。 對於圖片 — 您的標誌、背景圖形、裝飾元素 — 您有兩個選擇。要麼從同一個 Captive Portal 伺服器提供服務,這意味著它們位於同一個本地網路中,並且在驗證完成之前即可存取。或者,更好的方法是將它們作為 Base64 資料 URI 直接編碼在您的 HTML 或 CSS 中。這完全消除了外部依賴性。 現在讓我們來談談頁面版面配置。由於超過 90% 的 Captive Portal 登入發生在行動裝置上,您的設計應該是行動優先的。這意味著單欄版面配置,最大寬度約為 480 像素,並在頁面中置中。在 body 元素上使用 flexbox — display flex、flex-direction column、align-items centre、justify-content centre、min-height 100 viewport height。這會將您的內容卡片在任何螢幕尺寸上垂直和水平置中。 您的主要呼叫動作(CTA)按鈕需要易於觸控。Apple 的《人機介面指南》指定最小點按目標為 44 x 44 像素。在實踐中,對於主要 CTA,您會希望高度約為 48 像素,在容器內寬度全滿,邊框半徑(border-radius)約為 8 到 12 像素。 對於表單欄位 — 電子郵件輸入、姓名輸入 — 請將 font-size 設定為至少 16 像素。這至關重要。iOS Safari 和 CNA 會自動放大任何 font-size 低於 16 像素的輸入欄位,這會破壞您精心設計的版面配置。將 font-size 設定為 16 像素或以上可防止這種縮放行為。 法律同意部分值得特別注意。在 GDPR 規範下,如果您正在收集個人資料 — 即使只是電子郵件地址 — 您也需要明確、知情的同意。這意味著一個預設未勾選的核取方塊,並帶有清晰說明使用者同意內容的可見標籤。請勿預先勾選核取方塊。同意核取方塊本身必須清晰可見,無需捲動。 現在,特別針對 iOS CNA 的一個關鍵實作細節。當使用者完成驗證時,CNA 會監控 captive 網域是否已變得可存取。該檢查是由全頁導覽觸發的,而不是由 JavaScript AJAX 呼叫觸發。這意味著,如果您建置了一個單頁應用程式(SPA),該程式透過 fetch 或 XMLHttpRequest 提交表單,並在沒有全頁重新導向的情況下更新 DOM,則 CNA 將永遠無法偵測到驗證已完成。您必須在驗證後重新導向到新的 URL — 執行完整的 HTTP 重新導向,而不是 JavaScript DOM 操作。這是 Captive Portal 開發中最常見的錯誤之一。 對於 JavaScript,請保持極簡。CNA 的 JS 支援有限,且無法存取 localStorage 或 sessionStorage。當 CNA 關閉時,Cookie 會被銷毀。任何依賴這些瀏覽器 API 的狀態管理都將失敗。原生的 JavaScript 事件接聽程式是可以的。jQuery 是一個 30 KB 的外部依賴項,將會載入失敗。 [實作建議與陷阱] 讓我給您實用的實作清單。第一:務必使用 viewport meta 標籤。第二:所有 CSS 內聯,不使用外部樣式表。第三:所有圖片要麼由 Captive Portal 伺服器提供,要麼進行 Base64 編碼。第四:系統字型堆疊,不使用網路字型。第五:所有輸入欄位字型大小至少 16 像素。第六:易於觸控的點按目標,至少 44 x 44 像素。第七:單欄版面配置,最大寬度 480 像素。第八:驗證時進行全頁重新導向,而不是 JavaScript 狀態更新。第九:符合 GDPR 規範的同意核取方塊,預設未勾選。第十:在實際的 captive 網路上使用真實的 iOS 裝置進行測試,而不是瀏覽器預覽。 我在生產環境中最常看到的陷阱。第一:Google Fonts — 移除 import,它會失敗。第二:外部 JavaScript 程式庫 — Bootstrap、jQuery,任何 CDN 託管的指令碼都會失敗。第三:在外部樣式表中宣告的 CSS 變數 — 它們必須在您的內聯樣式區塊中。第四:透過 URL 參照的背景圖片 — 請對其進行 Base64 編碼。第五:沒有驗證後重新導向的 AJAX 表單提交 — CNA 將無法偵測到驗證完成。 現在,讓我們坦誠地談談自建與購買的對比。從頭開始建置自訂 Captive Portal 意味著您還必須負責後端基礎設施 — RADIUS 伺服器、資料庫、SSL 憑證、DNS 設定、與存取點的網路整合以及持續的安全修補。這是一項重大的工程投入。 Purple 的 portal 產生器為需要像素級完美控制的開發人員提供了一個拖放介面以及自訂 HTML 和 CSS 編輯器,同時處理所有後端基礎設施 — 驗證、資料收集、分析、GDPR 合規工具,以及與 200 多家存取點廠商的網路整合。您可以在沒有基礎設施開銷的情況下獲得創意控制權。 [快速問答] 我可以在 Captive Portal 中使用 CSS Grid 嗎?可以,但請特別在 iOS CNA 上進行測試。Flexbox 在較舊的 WebKit 版本中具有更廣泛的支援。我可以使用 SVG 標誌嗎?可以,內聯 SVG 得到完全支援,且對於標誌而言,比 Base64 編碼的 PNG 更佳,因為它們在 Retina 顯示器上能完美縮放。macOS CNA 是否支援與 iOS CNA 相同的限制?大致相同,只有一個區別:macOS CNA 在固定的 900 x 572 像素視窗中渲染。我可以使用像 Tailwind 這樣的 CSS 框架嗎?只有在您產生一個經過清除(purged)、自包含的 CSS 檔案並將其內聯到您的樣式區塊中時才可以。那 HTTPS 呢?您的 Captive Portal 必須透過 HTTP 提供服務,初始重新導向才能運作 — HTTPS 連線無法被 captive 網路攔截。 [總結與後續步驟] 總結今天的簡報。自訂 Captive Portal 是一個受限的網頁環境,而不是標準的瀏覽器環境。Apple CNA 和 Android webview 對外部資源、Cookie、JavaScript 和工作階段狀態施加了嚴格的限制。解決方案是建置自包含的 HTML 頁面,其中包含內聯 CSS、系統字型、Base64 編碼的圖片,並在驗證時進行全頁重新導向。 對於評估其選擇的場地營運商 and IT 團隊:如果您的需求是具有自訂 HTML 和 CSS 的完全品牌化、量身定制的 portal,那麼您需要在自行建置和維護完整堆疊(這是一項重大的工程投入)與使用像 Purple 這樣在生產級後端基礎設施之上提供自訂 HTML 和 CSS 編輯功能的平台之間做出選擇。 接下來的步驟:審查 Purple 的 portal 編輯器文件,根據我們今天涵蓋的行動優先清單稽核您現有的 portal,如果您是從頭開始,請使用我們概述的 HTML 範本結構作為您的基準。感謝您的收聽,我們下期簡報再見。

📚 核心系列的一部分:Captive Portal 終極指南

header_image.png

Executive Summary

For enterprise venues—ranging from luxury hotels Hospitality and retail chains Retail to transit hubs Transport and modern medical campuses Healthcare —the guest WiFi splash page is the digital front door. However, over 90% of guest WiFi logins occur on mobile devices, where rendering is governed not by standard browsers like Safari or Chrome, but by highly restricted Captive Network Assistant (CNA) webviews [1]. These "mini-browsers" enforce severe sandbox limitations: they block external CDNs, disable persistent cookies, ignore external web fonts, and severely restrict JavaScript execution to mitigate security risks and prevent session hijacking [2].

When a developer designs a splash page using traditional web standards, these constraints result in broken layouts, missing brand assets, and non-functional login buttons, directly impacting customer satisfaction and digital engagement. This guide provides solutions to these challenges, presenting defensive coding practices—such as inline CSS, Base64 asset encoding, system font stacks, and explicit navigation-driven authentication handshakes—to ensure seamless cross-platform rendering. Furthermore, we examine how utilising a managed solution like Purple's portal builder allows developers to maintain complete HTML/CSS creative control while offloading RADIUS authentication, database scaling, GDPR/PCI compliance, and multi-vendor AP integrations [3].

Technical Deep-Dive

To build a resilient custom captive portal, developers must understand the network-level interception and browser virtualisation that occurs when a guest associates with an open Service Set Identifier (SSID).

The Captive Portal Lifecycle

When a client device associates with a captive SSID, the following sequence is triggered:

  1. IP Association: The device completes a 3-way handshake and requests an IP address via DHCP.
  2. Active Connectivity Probe: The operating system's background network manager immediately sends an HTTP GET request to a dedicated vendor-neutral canary URL (e.g., Apple's http://captive.apple.com/hotspot-detect.html or Google's http://connectivitycheck.gstatic.com/generate_204) [1].
  3. DNS/HTTP Interception: The local Wireless LAN Controller (WLC) or Access Point (AP) intercepts this port 80 HTTP request. Instead of returning the expected HTTP 200 or 204 status, the gateway redirects the client's traffic to the captive portal's landing page URL via an HTTP 302 redirect [2].
  4. Webview Spawning: Detecting the redirect, the OS spawns its native Captive Network Assistant (CNA) mini-browser to display the redirected splash page, bypassing the need for the user to manually open a full browser.
  5. Authentication and State Transition: The user completes the login form, submitting credentials back to the portal server, which instructs the gateway (often via a RADIUS Access-Accept or external API call) to authorise the MAC address.
  6. CNA Exit Handshake: The CNA mini-browser performs another HTTP GET to its canary URL. If it receives the expected 200/204 response, it changes its top-right button from "Cancel" to "Done" and establishes the WiFi connection as the primary network interface.

Platform-Specific Mini-Browser Constraints

Each operating system handles this lifecycle within different webview environments, resulting in highly fragmented behaviour. The table below details these critical constraints:

Platform / Webview Display Method Persistent Cookies External Web Fonts JavaScript Execution Window Dimensions Exit Handshake Trigger
Apple iOS CNA (Websheet) Mini-Browser Popup Blocked (Destroyed on close) Blocked (Offline) Limited (No localStorage/sessionStorage) Responsive (Device-width) Full-page HTTP Redirect Only [1]
Apple macOS CNA (Captive Network Assistant) Mini-Browser Popup Blocked Blocked Limited (No alert/confirm dialogs) Fixed (900px x 572px) Full-page HTTP Redirect Only
Android (Google) (CaptivePortalLogin) Push Notification -> Chrome Custom Tab Allowed (Shared with Chrome) Allowed (If whitelisted in walled garden) Full Responsive Automatic (Captive Portal API / 204 Check) [2]
Samsung Android (Samsung Internet) Push Notification -> Mini-Browser Allowed Allowed Full Responsive Automatic
Windows 10/11 (Default Browser) Auto-Launch Default Browser Allowed (Full browser context) Allowed Full Responsive Manual / Automatic

cna_constraints_comparison.png

Coding Around the Apple CNA "Done" Button Trap

One of the most frequent failure modes in custom portal development is the "Done" Button Trap on iOS devices. When a user authenticates, the iOS Websheet webview must detect that the network is no longer captive. It does this by monitoring the success of its background canary requests.

Crucially, the iOS CNA will only trigger this check upon a full-page HTTP navigation (location redirect). If a developer builds a modern Single Page Application (SPA) that submits form data via an asynchronous AJAX call (e.g., fetch() or Axios) and updates the DOM dynamically without changing the URL, the CNA will never re-run its connectivity check. The user will be authenticated at the gateway level, but the CNA button in the top-right corner will remain as "Cancel". If the frustrated user clicks "Cancel", the iOS device will immediately disassociate from the SSID, terminating the WiFi session [1].

To prevent this, the authentication success handler must perform a full-page redirect to a physical landing page (e.g., window.location.href = '/success') or submit the login form natively via a standard HTTP POST action.

Implementation Guide

To ensure consistent rendering across all platforms, developers must transition from modern, asset-heavy web design to a highly self-contained, defensive coding style.

The Golden Rule: Design for Zero Internet Connectivity

During the captive state, the client device has no access to the wider internet. It can only resolve and access IP addresses and domains explicitly whitelisted in the wireless controller's Walled Garden (such as the IP of the captive portal server itself). Therefore, any external asset referenced in your HTML will fail to load, resulting in a broken layout.

To design defensively, implement the following Mobile-First Captive Portal Design Checklist:

mobile_first_checklist.png

1. Viewport Configuration

To prevent mobile devices from scaling down the viewport to a desktop width (typically 980px), the HTML `` must include a responsive viewport meta tag. Without this, text and input fields will appear microscopic on mobile devices:


2. Inlining CSS and Removing External Dependencies

Never link to external CSS files or CDNs (e.g., Bootstrap, Tailwind, or Google Fonts). All CSS must be embedded within a `

<div class="portal-card">
    <div class="logo-container">
        
        
            
            YOUR BRAND
        
    </div>
    
    <h1>Welcome to Guest WiFi</h1>
    <p>Please enter your details below to gain secure, high-speed internet access.</p>
    
    
    
        <div class="form-group">
            Full Name
            
        </div>
        
        <div class="form-group">
            Email Address
            
        </div>
        
        <div class="consent-group">
            
            
                I accept the <a href="#">Terms of Service</a> and consent to data processing in compliance with GDPR regulations.
            
        </div>
        
        <div id="terms_box" class="terms-scrollbox">
            <strong>WiFi Terms of Service:</strong><br />
            1. This service is provided as-is without warranties.<br />
            2. Users must not engage in illegal bandwidth-intensive activities.<br />
            3. Personal data is collected solely for authentication and marketing opt-ins in compliance with our Privacy Policy.
        </div>
        
        Connect to WiFi
    
    
    <div class="footer">
        Powered by Purple | Secure Guest WiFi
    </div>
</div>

## Troubleshooting &amp; Risk Mitigation

When deploying custom-coded HTML/CSS captive portals, IT operations teams frequently encounter several severe operational risks:

### 1. The SSL/TLS Certificate Warning Loop

Because captive portals function by intercepting traffic, they present a fundamental conflict with modern HTTPS web security. When a user attempts to visit an HTTPS site (e.g., `https://www.google.com`), and the gateway attempts to redirect that traffic to an HTTP captive portal, the browser detects a mismatch in the SSL certificate and displays a critical "Your connection is not private" security warning. 

* **Mitigation**: Never attempt to intercept HTTPS traffic directly. Rely entirely on the operating system's native CNA helper (which makes an unencrypted HTTP request to trigger the redirect). Ensure your captive portal's domain has a valid, publicly trusted SSL certificate (e.g., Let's Encrypt or DigiCert) and is served over HTTPS *only after* the initial HTTP redirect has successfully routed the user to your portal domain [2].

### 2. DNS Resolution Failures (The Walled Garden Trap)

If your custom HTML page references external resources—such as a social login OAuth endpoint (e.g., Facebook, Google) or a payment gateway—the DNS requests for these domains will fail unless they are explicitly whitelisted in the wireless controller's Walled Garden. If a domain is missing from the whitelist, the login flow will stall, presenting a blank screen.

* **Mitigation**: Maintain a strict, minimal Walled Garden list. If utilising social logins, whitelist the specific wildcard domains recommended by the identity providers (e.g., `*.google.com`, `*.gstatic.com`). 

### 3. Session Timeout and MAC Spoofing Vulnerabilities

Standard captive portals authenticate devices based on their MAC addresses. However, modern mobile operating systems (iOS 14+ and Android 10+) utilise randomised MAC addresses (private WiFi addresses) by default, rotating them periodically. This can lead to guests being repeatedly prompted to re-authenticate, destroying the user experience [1].

* **Mitigation**: Implement reasonable session timeouts (e.g., 24 hours) on the RADIUS server to prevent stale sessions, and utilise modern authentication standards like **Passpoint (Hotspot 2.0)** or **WPA3-Enterprise** for seamless, secure onboarding that bypasses MAC-based captive portals entirely.

## Purple Product Relevance: Build vs. Buy

While coding a single HTML page is straightforward, hosting, securing, and scaling a custom captive portal infrastructure presents massive technical and compliance hurdles. The table below compares the engineering and operational realities of self-hosting a custom portal versus utilising Purple's managed enterprise platform:

| Feature / Operational Requirement | Self-Hosted Custom Portal | Purple Enterprise WiFi Platform |
| :--- | :--- | :--- |
| **HTML/CSS Customisation** | Fully manual coding, uploading files to individual APs or local web servers. | **Pixel-perfect developer editor** allowing custom HTML/CSS injects, combined with a drag-and-drop visual builder.
| **RADIUS Infrastructure** | Must deploy, configure, and maintain highly available FreeRADIUS or Cloud RADIUS servers [4]. | **Built-in, globally distributed, cloud-native RADIUS** with active-active redundancy and 99.99% uptime SLAs.
| **Multi-Vendor AP Support** | Custom integration scripts required for each hardware vendor (Cisco, Aruba, Meraki, Ruckus) [5]. | **Native, out-of-the-box integration** with over 200 hardware models; unified portal deployment across mixed-hardware estates.
| **Data Privacy &amp; Compliance** | Venue assumes 100% legal liability for GDPR, CCPA, and PCI DSS compliance, including secure database encryption and data deletion workflows. | **Fully compliant by design**. Built-in consent management, automated data-subject deletion requests, and secure ISO 27001-certified hosting.
| **Analytics &amp; Marketing** | Requires building custom data ingestion pipelines and integrating third-party marketing tools. | **Enterprise-grade analytics dashboard** with real-time footfall tracking, return-rate metrics, and automated marketing campaign triggers [6].
| **Identity Provider Integrations** | Manual OAuth2 integrations with Google, Facebook, Apple, and local SMS gateways. | **One-click integrations** with major social platforms, SMS gateways, and Azure AD / Okta for corporate guests.

Purple's platform resolves the "Build vs. Buy" dilemma. It provides developers with the complete creative freedom of a custom HTML/CSS workspace while eliminating the complex, high-risk backend infrastructure engineering required to support secure RADIUS authentication at scale.

## ROI &amp; Business Impact

Investing in a professionally engineered, responsive custom captive portal delivers quantifiable returns across IT operations, marketing, and legal compliance.

### 1. Operational Cost Reduction (IT Helpdesk Tickets)

In large-scale deployments, such as a stadium or multi-site retail chain, a broken captive portal is a leading driver of IT helpdesk escalations. When guests encounter a "white screen" or a non-responsive login button, they overwhelm on-site staff or submit support tickets.

$$\text{Annual Support Savings} = (\text{Total Annual Guest Visits} \times \text{Portal Failure Rate} \times \text{Helpdesk Contact Rate}) \times \text{Cost Per Support Ticket}$$

* **Scenario**: A convention centre with 1,000,000 annual visitors. A poorly coded portal has a 5% failure rate on older iOS devices, leading to a 10% helpdesk contact rate. At an industry-standard $15 per support ticket, the operational cost is:
  $$(1,000,000 \times 0.05 \times 0.10) \times \$15 = \$75,000 \text{ annually in avoidable support overhead}$$
* **Outcome**: Transitioning to a CNA-optimised, mobile-first template reduces the portal failure rate to &lt;0.1%, virtually eliminating this operational drain.

### 2. Marketing Data Capture and Opt-in Optimisation

For retail and hospitality venues, the guest WiFi portal is the primary mechanism for capturing clean, first-party customer data. A poorly designed user interface with microscopic text or a clunky form layout causes high **bounce rates**—users abandon the login process entirely, resulting in lost marketing opportunities.

* **Case Study (Retail)**: A national retail chain implemented a mobile-first optimised captive portal utilising Purple's platform. By replacing a multi-step login form with a single-field email input (font-size: 16px) and an optimised 48px tap-target button, they saw a **42% increase in completed registrations** and a **28% increase in marketing newsletter opt-ins** within the first quarter [6].

### 3. Legal and Regulatory Risk Mitigation

Under GDPR and CCPA, non-compliant data collection carries severe financial penalties (up to 4% of global annual turnover under GDPR). Relying on pre-ticked checkboxes or failing to provide a clear, easily accessible Privacy Policy on your splash page exposes the enterprise to immense legal liability.

* **Mitigation ROI**: Implementing an explicit, un-ticked consent checkbox and hosting terms within an optimised scrollbox ensures 100% regulatory compliance, mitigating the risk of multi-million dollar regulatory fines and protecting brand reputation.

## Summary of Key Takeaways

* **The CNA Sandbox is Restrictive**: Apple's iOS Websheet and macOS CNA are highly sandboxed environments that block external assets, cookies, and web fonts. All styling and assets must be self-contained (inline CSS, Base64 images, system fonts) [1].
* **AJAX Breaks the iOS Exit Handshake**: To successfully transition the iOS device from "captive" to "connected" (changing the top-right button from "Cancel" to "Done"), you must trigger a full-page HTTP redirect. Asynchronous DOM updates will leave the device in a captive loop.
* **Mobile-First is Mandatory**: Over 90% of logins occur on mobile. Design a single-column layout (max-width: 480px), utilise touch-friendly tap targets (minimum 44px x 44px), and enforce a minimum 16px font size on all text inputs to prevent automatic iOS browser zooming.
* **Walled Gardens Control DNS**: Any external domain referenced during login (e.g., social login APIs) must be explicitly whitelisted in the wireless controller's walled garden, or the page will fail to load.
* **Purple Eliminates Backend Complexity**: Utilising Purple's portal builder gives developers complete HTML/CSS control via a custom editor, while offloading the immense security, scaling, and compliance burdens of RADIUS, multi-vendor AP integrations, and GDPR-compliant database management [3].

## References

* [1] [Wireless Broadband Alliance: Captive Network Portal Behaviour](https://captivebehavior.wballiance.com/)
* [2] [Android Open Source Project: Captive Portal Login Webview Integration](https://source.android.com/docs/core/connect/android-custom-tabs-captive-portal)
* [3] [European Data Protection Board: Guidelines on Consent under Regulation 2016/679](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/guidelines-052020-consent-under-regulation-2016679_en)
* [4] [How to Implement 802.1X Authentication with Cloud RADIUS](/guides/implementing-8021x-with-cloud-radius)
* [5] [Cisco Wireless APs: 2026 Guide to Products &amp; Deployment](/blog/cisco-wireless-ap)
* [6] [Purple WiFi Marketing &amp; Analytics Platform](/guest-wifi-marketing-analytics-platform)

---

## Listen to the Technical Briefing

Listen to a senior solutions architect discuss the technical constraints and implementation strategies for custom captive portals:

關鍵定義

Captive Portal

在向新連接 Wi-Fi 網路的使用者授予更廣泛的網路資源存取權限之前,向其顯示的網頁,通常用於驗證、付款或顯示服務條款。

IT 團隊在閘道器層級部署 Captive Portal,以控制訪客存取、收集使用者資料並執行法律合規性。

Captive Network Assistant (CNA)

作業系統(例如 Apple iOS 和 macOS)在偵測到 captive 網路重新導向時自動產生的、受到高度限制且處於沙箱環境中的微型瀏覽器,其設計目的僅在於協助進行 portal 驗證。

CNA webviews 執行嚴格的限制,包括封鎖外部 CDN、持久性 Cookie 和本機儲存,這經常會破壞標準的網頁設計。

Walled Garden

在完成 Captive Portal 登入流程之前,允許未經驗證的訪客使用者透過閘道器存取的 IP 位址、子網路或網域名稱的受限清單。

開發人員必須確保任何外部資源(例如社群登入 API 或付款閘道器)都已列入 walled garden(圍牆花園)白名單,以防止登入流程停滯。

Base64 Encoding

一種二進位轉文字的編碼配置,將二進位資料(例如圖片)表示為 ASCII 字串,允許將資產直接嵌入到 HTML 或 CSS 文件中。

對標誌和圖示使用 Base64 編碼可消除外部 HTTP 請求,確保資產在離線 CNA 環境中完美渲染。

RADIUS (Remote Authentication Dial-In User Service)

一種網路協定,為連接和使用網路服務的使用者提供集中式的驗證、授權和計費(AAA)管理。

一旦滿足驗證條件,Captive Portal 伺服器就會與 RADIUS 伺服器進行通訊,以在網路閘道器端授權訪客的 MAC 位址。

System Font Stack

一種 CSS font-family 宣告,其優先使用預先安裝的作業系統字型(例如 iOS 上的 San Francisco、Windows 上的 Segoe UI 和 Android 上的 Roboto),而非外部網路字型。

實作系統字型堆疊可確保立即進行排版渲染,而不會觸發對 Google Fonts 等服務的被封鎖外部 HTTP 請求。

Canary URL

由作業系統廠商維護的專用、未加密的 HTTP URL(例如 captive.apple.com),用於測試裝置是否具有不受限制的網際網路連線能力。

作業系統背景網路管理員會檢查此 URL,以偵測是否存在 Captive Portal 並觸發 CNA webview 彈出視窗。

Passpoint (Hotspot 2.0)

由 Wi-Fi Alliance 開發的產業標準,使行動裝置能夠自動偵測 Wi-Fi 熱點並與其進行安全驗證,從而繞過手動的 Captive Portal 登入。

企業將 Passpoint 與 Purple 等平台結合使用,使訪客從繁瑣的登入頁面過渡到無縫、類似行動網路的安全漫遊體驗。

範例

一家擁有 250 間客房的奢華連鎖酒店 [Hospitality](/industries/hospitality) 希望實作一個完全符合其高端品牌指南的自訂訪客 WiFi 登入頁面。他們的創意代理商設計了一個登入頁面(splash page),其中使用了自訂品牌字型(託管於 Adobe Fonts)、多張高解析度背景圖片(託管於公開的 AWS S3 儲存桶)以及多步驟動畫 JavaScript 精靈。部署後,iOS 訪客連接到 SSID,但 portal 彈出時顯示為空白畫面,且使用者無法進行驗證。

為了解決空白畫面和品牌呈現破裂的問題,我們必須重構 portal 的前端架構,以符合 Apple CNA 沙箱限制:

  1. 字型修復:由於 Adobe Fonts 需要外部 HTTP 請求,而該請求會被 CNA 封鎖,因此我們將自訂字型呼叫替換為原生的高端系統字型堆疊(font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;)。這可確保在沒有外部網路呼叫的情況下立即進行渲染。
  2. 資產最佳化:AWS S3 上的背景圖片被封鎖,因為 S3 不在閘道器的 walled garden(圍牆花園)中。我們壓縮主要品牌標誌,將其轉換為輕量級的 SVG,並將其作為 Base64 Data URI 直接編碼在 HTML 中。對於背景,我們使用酒店的品牌色彩,以乾淨、響應式的 CSS 漸層取代沉重的圖片,從而大幅減輕頁面重量。
  3. JavaScript 簡化:多步驟動畫精靈依賴外部 jQuery 和 GSAP 程式庫。我們移除這些外部依賴項,並將表單重構為單頁、單欄的 HTML 結構。表單驗證使用輕量級的原生 JavaScript 重寫。
  4. 驗證交握:表單提交方式從基於 AJAX 的提交修改為原生 HTML <form action="/submit" method="POST">,以觸發全頁重新導向,從而允許 iOS Websheet 執行其 canary 檢查並顯示「完成」按鈕。
考官評語: 此情境代表了高端創意設計與 captive webview 嚴格安全限制之間的經典衝突。創意代理商通常會將 Captive Portal 視為標準的桌上型電腦網站。然而,由於裝置處於未驗證狀態,網路會封鎖所有外部流量。透過將 CSS 內聯、使用系統字型堆疊、對資產進行 Base64 編碼以及使用原生表單提交,我們在保留高端品牌美學的同時,在 iOS 和 Android 裝置上實現了 100% 的運作可靠性。

一家擁有 450 家門市的連鎖零售商 [Retail](/industries/retail) 希望透過 WiFi 登入頁面收集訪客電子郵件,以充實其 CRM。他們要求訪客選擇訂閱行銷電子報。最初的設計包含一個預先勾選的「我同意接收行銷電子郵件」核取方塊。此外,該 portal 託管於其總部的單一本地伺服器上。在尖峰時段(週六下午),全國各地的訪客都遇到了嚴重的延遲,許多人無法載入登入頁面,導致資料收集率大幅下降。

我們必須同時解決合規性違規和基礎設施瓶頸問題:

  1. 合規性修復:在 GDPR 和 CCPA 規範下,預先勾選的同意方塊是非法的。我們修改 HTML,使行銷同意核取方塊預設為未勾選(<input type="checkbox" id="marketing_consent">)。我們還為服務條款添加了一個獨立的強制性核取方塊,以將法律協議與行銷訂閱解耦。
  2. 基礎設施擴充:將全國性的 Captive Portal 託管在單一集中式伺服器上會造成單一故障點和巨大的延遲瓶頸。我們將 portal 前端遷移到具有邊緣快取、高可用性且全球分佈的內容傳遞網路(CDN)。
  3. RADIUS 整合:我們設定本地門市的存取點,使其指向具有主動-主動(active-active)備援的雲端原生 RADIUS 叢集,確保即使在週六尖峰流量期間,驗證請求也能在邊緣本地進行處理,且延遲低於 50 毫秒。
  4. Purple 遷移:為了消除這整個工程開銷,該零售商遷移到了 Purple。Purple 內建的 GDPR 同意工具會自動管理合規的訂閱,其全球分佈的雲端基礎設施每天處理數百萬次驗證,可用性達 99.99%,徹底解決了擴充瓶頸。
考官評語: 預先勾選的同意核取方塊代表嚴重的合規風險,可能導致鉅額監管罰款。將行銷同意與服務條款解耦是技術和法律上的最佳實踐。在基礎設施方面,集中託管 Captive Portal 是一種反模式(anti-pattern)。全國性的零售版圖需要去中心化、邊緣快取的前端,並結合雲端原生的 RADIUS 後端。遷移到像 Purple 這樣的託管平台可以消除這種架構複雜性,使零售商能夠專注於行銷活動,而不是資料庫擴充。

練習題

Q1. 一家大型國際機場 [Transport](/industries/transport) 的 IT 團隊部署了一個自訂編碼的 Captive Portal。他們注意到,雖然 Android 使用者可以無縫連接,但很大一部分 iOS 使用者遇到了成功驗證但無法瀏覽網頁的問題。仔細檢查後,iOS 裝置顯示已連接到 SSID,但 captive 彈出視窗右上角的按鈕仍然顯示「取消」而不是「完成」。此問題的根本原因是什麼?開發人員應該如何修復它?

提示:分析 Apple CNA 協助程式如何偵測網路已從 captive 狀態轉換為已驗證狀態,以及需要什麼瀏覽器動作來觸發此檢查。

查看標準答案

根本原因在於 portal 的成功頁面是透過 JavaScript(AJAX/SPA 路由)動態更新 UI,而不是執行全頁 HTTP 導覽。Apple iOS Captive Network Assistant (CNA) 微型瀏覽器僅在發生全頁 URL 重新導向或導覽時,才會重新執行其背景連線能力檢查(對 captive.apple.com 的 canary 請求)。如果開發人員透過 AJAX 提交登入表單,並僅在 DOM 中顯示「成功」訊息,則 CNA 將無法得知網路已解鎖。因此,右上角的按鈕仍保持為「取消」。如果使用者按一下「取消」退出,作業系統會判定登入失敗並中斷與 WiFi 網路的連線。

解決方案:開發人員必須修改驗證成功處理常式以強制進行全頁重新導向。這可以透過標準 HTML <form action="/submit" method="POST"> 原生提交登入表單,或在 API 回傳成功驗證回應後在 JavaScript 中執行 window.location.href = '/success_landing_page' 來實現。這會觸發所需的全頁載入,強制 CNA 協助程式重新評估網路狀態,驗證現在是否可以存取 canary URL,並將右上角的按鈕變更為「完成」。

Q2. 一個體育場營運團隊 [Events] 希望推出一個可收集行銷訂閱的訪客 WiFi 網路。合規官堅持 portal 必須 100% 符合 GDPR 規範。開發團隊展示了一個模型,其中登入表單包含一個預先勾選的方塊,內容為「我同意服務條款並同意接收行銷電子報」。為什麼這種設計不合規?應該如何重構 HTML/CSS 和表單結構以滿足 GDPR,同時保持高轉換率?

提示:考量 GDPR 對於明確同意、將行銷訂閱與服務條款解耦,以及法律條文在行動裝置螢幕上的實際可見性的嚴格要求。

查看標準答案

所提出的設計在兩個主要方面違反了 GDPR:首先,預先勾選的核取方塊不構成有效的同意,同意必須是自由給予、具體、知情且明確的。其次,將行銷同意與同意服務條款捆綁在一起是不合規的;不能強制使用者接受行銷電子郵件作為使用 WiFi 服務的條件。

重構策略

  1. 解耦同意:將核取方塊拆分為兩個獨立的核取方塊。核取方塊 A 是強制性的,涵蓋服務條款和隱私權政策。核取方塊 B 是選填的,涵蓋行銷電子報訂閱。
  2. 設定為未勾選:確保 HTML 中預設未勾選這兩個核取方塊(省略 checked 屬性)。
  3. CSS 可見性:由於超過 90% 的使用者使用行動裝置,請將核取方塊直接放置在「連接」按鈕上方,以便在不捲動的情況下在「首屏」(above the fold)可見。使用系統字型堆疊,並將標籤字型大小設定為 14px,行高(line-height)設定為 1.4,以提高可讀性。
  4. 條款捲動方塊:為了防止法律條文將表單元素擠出螢幕,請將詳細的服務條款放在具有固定高度的捲動容器中(max-height: 100px; overflow-y: auto; background-color: #F5F1ED; border: 1px solid #D1D5DB; border-radius: 6px;),該容器可以透過文字連結切換開啟或關閉。這在確保絕對法律合規的同時,保持了乾淨且高轉換率的版面配置。

Q3. 一家連鎖零售商 [Retail](/industries/retail) 正在 100 家門市部署自訂編碼的登入頁面。設計師使用了 Google Fonts (Montserrat),並在 HTML head 中連結到 CDN 託管的 Bootstrap 樣式表。在公司網路進行測試期間,頁面渲染非常美觀。然而,當部署到具有 captive 網路設定的測試門市 AP 時,頁面渲染卻顯示為未套用樣式的 Times New Roman 文字、對齊破裂且缺少圖示。為什麼會發生這種情況?資產必須如何重構?

提示:分析使用者驗證前網路連線的狀態,並確定瀏覽器如何處理對 walled garden(圍牆花園)以外網域的外部 HTTP 請求。

查看標準答案

此失敗是由於在載入登入頁面時,裝置處於未驗證的 captive 狀態。在此狀態下,無線閘道器會封鎖所有連外網際網路流量,僅允許對閘道器 Walled Garden(圍牆花園)中明確列入白名單的網域進行請求。由於 Bootstrap (cdn.jsdelivr.net) 和 Google Fonts (fonts.googleapis.com) 的 CDN 網域未列入白名單,瀏覽器獲取樣式表和字型檔案的請求會靜默失敗。因此,瀏覽器會退回到其預設的渲染引擎,導致未套用樣式的 HTML(Times New Roman 文字)和破裂的版面配置。

重構策略

  1. 內聯 CSS:移除外部 Bootstrap 樣式表連結。將必要的 CSS grid/flexbox 規則直接複製到 HTML <head> 中的 <style> 區塊中。這可確保所有版面配置指令都在初始的單頁負載中傳遞。
  2. 實作系統字型堆疊:移除 Google Fonts @import<link> 呼叫。在 CSS 中將其替換為原生系統字型堆疊(font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;)。這會強制裝置使用作業系統中已預先安裝的高品質字型,從而完全消除外部網路依賴性。
  3. 對圖示/標誌進行 Base64 編碼:如果版面配置依賴外部圖片或圖示庫(如 FontAwesome),請將這些圖示轉換為 SVG 格式,並直接嵌入到 HTML 中,或在 CSS 中作為 Base64 Data URI 嵌入。這保證了頁面是 100% 自包含的,即使在完全沒有網際網路連線的情況下也能完美渲染。