萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

JS + PHP 實現靜態頁面實時顯示用戶登錄狀態

場景

靜態 HTML 頁面 (CDN 緩存、Nginx 直接服務) 無法直接讀取 Session/Cookie。通過 <script src="auth_status.php"> 讓 PHP 動態輸出 JavaScript 代碼,實現「靜態頁 + 動態用戶狀態」。

架構圖

[靜態 HTML] --> 瀏覽器解析 --> 請求 auth_status.php?callback=xxx
                                    ↓
                              [PHP 讀取 Session/Cookie]
                                    ↓
                              輸出 document.write('...') 或 callback({...})
                                    ↓
                              瀏覽器執行 JS 更新 DOM

服務端:auth_status.php

<?php
// auth_status.php
header('Content-Type: application/javascript; charset=UTF-8');

// 1. 讀取用戶狀態(示例:Session)
session_start();
$isLoggedIn = !empty($_SESSION['user_id']);
$userName   = $isLoggedIn ? htmlspecialchars($_SESSION['user_name']) : '';
$userId     = $isLoggedIn ? (int)$_SESSION['user_id'] : 0;

// 2. 支援 JSONP 回調(跨域場景)
$callback = $_GET['callback'] ?? null;
if ($callback && !preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $callback)) {
    $callback = null; // 防 XSS
}

// 3. 構建數據
$data = [
    'loggedIn' => $isLoggedIn,
    'userId'   => $userId,
    'userName' => $userName,
    'avatar'   => $isLoggedIn ? '/avatar/' . $userId . '.jpg' : '',
    'logoutUrl'=> '/logout.php',
    'loginUrl' => '/login.php?redirect=' . urlencode($_SERVER['HTTP_REFERER'] ?? '/'),
];

// 4. 輸出
if ($callback) {
    // JSONP
    echo $callback . '(' . json_encode($data, JSON_UNESCAPED_UNICODE) . ');';
} else {
    // 直接輸出 JS 變量/函數調用(同域)
    echo "window.__USER_STATUS__ = " . json_encode($data, JSON_UNESCAPED_UNICODE) . ";";
    // 或直接寫 DOM(簡單但不推薦,阻塞渲染)
    // echo "document.getElementById('user-area').innerHTML = " . json_encode($html) . ";";
}

前端:靜態頁面嵌入

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>靜態頁面</title>
</head>
<body>
    <div id="user-area">載入中...</div>

    <!-- 同域:直接定義全局變量 -->
    <script src="/auth_status.php"></script>
    
    <script>
    // 等待變量就緒 (腳本異步加載,需監聽)
    function initUserArea() {
        if (!window.__USER_STATUS__) return setTimeout(initUserArea, 50);
        const s = window.__USER_STATUS__;
        const el = document.getElementById('user-area');
        if (s.loggedIn) {
            el.innerHTML = `歡迎, <a href="/profile?id=${s.userId}">${s.userName}</a> | <a href="${s.logoutUrl}">退出</a>`;
        } else {
            el.innerHTML = `<a href="${s.loginUrl}">登錄</a> / <a href="/register.php">註冊</a>`;
        }
    }
    initUserArea();
    </script>
</body>
</html>

跨域場景:JSONP

靜態頁在 static.example.com,認證服務在 api.example.com:

<script>
function renderUser(data) {
    const el = document.getElementById('user-area');
    if (data.loggedIn) {
        el.innerHTML = `歡迎, ${data.userName} | <a href="${data.logoutUrl}">退出</a>`;
    } else {
        el.innerHTML = `<a href="${data.loginUrl}">登錄</a>`;
    }
}
</script>
<script src="https://api.example.com/auth_status.php?callback=renderUser"></script>

現代替代方案對比

方案優點缺點適用場景
JS+PHP (本文)無框架依賴、兼容極舊瀏覽器、CDN 友好阻塞渲染、XSS 風險、維護困難老項目、郵件模板、純靜態托管
AJAX + API非阻塞、關注點分離、易測試需處理 CORS、額外請求現代 SPA/SSR
SSI (Server Side Includes)Nginx/Apache 原生、極快需服務器配置、不支援動態邏輯高性能靜態站點
Edge Side Includes (ESI)Varnish/Cloudflare 支援、緩存片段基礎設施複雜大型 CDN 架構
Web Components / Shadow DOM封裝性好、框架無關瀏覽器兼容性、需 Polyfill微前端、組件化

安全加固

  • CSP:Content-Security-Policy: script-src 'self' 'nonce-...',配合 nonce 替代內聯腳本。
  • HttpOnly Cookie:Session ID 設置 HttpOnly; Secure; SameSite=Lax,JS 無法讀取,防 XSS 竊取。
  • 輸出編碼:所有動態插入 HTML 的字符串必須 htmlspecialchars。
  • JSONP 白名單:嚴格驗證 callback 參數格式。

總結

JS+PHP 動態注入是解決「靜態頁面顯示動態用戶狀態」的經典折中方案。核心模式:靜態頁引入動態 JS → PHP 讀取會話 → 輸出數據/渲染代碼 → 前端更新 DOM。現代項目優先選 AJAX/API 模式,老系統或極簡場景仍可使用本模式,但務必做好 XSS 防護與 CSP 配置。

copyright © 萬盛學電腦網 all rights reserved