You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何制作仅允许特定IP访问的HTML(含CSS/PHP/JavaScript)页面

嘿,我来给你捋捋几种可行的实现思路——首先得明确:前端(HTML/JS)单独做IP授权完全不靠谱,因为用户随便就能篡改前端代码或者禁用JS绕过去。所以核心验证逻辑必须放在后端(比如PHP),前端顶多做个友好的辅助提示。下面具体说:

核心方案:PHP后端IP授权(最安全可靠)

这是生产环境里的标准做法,所有请求先经过后端IP校验,不通过直接拒绝访问,完全不给前端内容暴露的机会。

<?php
// 第一步:定义允许访问的IP白名单(支持单个IP或CIDR网段)
$allowed_ips = [
    '192.168.1.100',
    '10.0.0.5',
    '192.168.2.0/24' // 允许整个网段的示例
];

// 第二步:获取用户真实IP(处理反向代理/CDN场景,避免拿到代理IP)
function get_real_user_ip() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // 处理多代理情况,取第一个非内网的真实IP
        $ip_list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        foreach ($ip_list as $ip) {
            $clean_ip = trim($ip);
            // 过滤内网IP,确保拿到真实公网IP
            if (filter_var($clean_ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $clean_ip;
            }
        }
    }
    // 没有代理时直接取REMOTE_ADDR
    return $_SERVER['REMOTE_ADDR'];
}

$user_ip = get_real_user_ip();

// 第三步:校验IP是否在白名单内
function is_ip_allowed($user_ip, $allowed_ips) {
    foreach ($allowed_ips as $allowed_ip) {
        // 精确匹配单个IP
        if ($user_ip === $allowed_ip) {
            return true;
        }
        // 匹配CIDR网段(比如192.168.2.0/24)
        if (strpos($allowed_ip, '/') !== false) {
            list($subnet, $mask) = explode('/', $allowed_ip);
            $user_ip_long = ip2long($user_ip);
            $subnet_long = ip2long($subnet);
            $mask_long = ~((1 << (32 - $mask)) - 1);
            if (($user_ip_long & $mask_long) === ($subnet_long & $mask_long)) {
                return true;
            }
        }
    }
    return false;
}

$is_authorized = is_ip_allowed($user_ip, $allowed_ips);

// 第四步:根据校验结果处理访问权限
if (!$is_authorized) {
    // 返回403禁止访问状态码,同时显示友好提示页
    header('HTTP/1.1 403 Forbidden');
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <title>访问被拒绝</title>
        <style>
            body { font-family: Arial, sans-serif; text-align: center; margin: 100px auto; max-width: 600px; }
            .error-card { padding: 2rem; border-radius: 8px; background-color: #f8d7da; border: 1px solid #dc3545; color: #721c24; }
        </style>
    </head>
    <body>
        <div class="error-card">
            <h2>403 访问被拒绝</h2>
            <p>你的IP地址未获得访问此页面的授权</p>
        </div>
    </body>
    </html>
    <?php
    exit; // 终止脚本,后续内容不会输出
}

// 授权通过,输出正常页面内容
?>
<!DOCTYPE html>
<html>
<head>
    <title>授权页面</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin: 100px auto; max-width: 600px; }
        .welcome-card { padding: 2rem; border-radius: 8px; background-color: #d4edda; border: 1px solid #28a745; color: #155724; }
    </style>
</head>
<body>
    <div class="welcome-card">
        <h2>欢迎访问授权页面</h2>
        <p>你的IP地址已通过验证</p>
    </div>
</body>
</html>
前端辅助:JavaScript快速提示(仅做体验优化,不能替代后端)

如果想给用户更快的反馈,可以在前端加个JS校验,但绝对不能只靠这个——懂技术的用户很容易篡改JS代码绕过限制,必须和后端验证配合使用。

<!DOCTYPE html>
<html>
<head>
    <title>IP授权页面</title>
    <style>
        .hidden { display: none; }
        .container { text-align: center; margin: 100px auto; max-width: 600px; }
        .error-card { padding: 2rem; border-radius: 8px; background-color: #f8d7da; border: 1px solid #dc3545; color: #721c24; }
        .content-card { padding: 2rem; border-radius: 8px; background-color: #d4edda; border: 1px solid #28a745; color: #155724; }
    </style>
</head>
<body>
    <div class="container">
        <div id="error" class="error-card">
            <h2>访问被拒绝</h2>
            <p>你的IP地址未被授权</p>
        </div>
        <div id="content" class="content-card hidden">
            <h2>欢迎访问</h2>
            <p>这是仅授权用户可见的内容</p>
        </div>
    </div>

    <script>
        // 前端白名单(注意:这个会暴露在源码里,所以必须后端再校验一次)
        const allowedIPs = ['192.168.1.100', '10.0.0.5'];

        // 通过第三方API获取用户IP(浏览器本身没有直接获取IP的API)
        fetch('https://api.ipify.org?format=json')
            .then(res => res.json())
            .then(data => {
                const userIP = data.ip;
                if (allowedIPs.includes(userIP)) {
                    document.getElementById('error').classList.add('hidden');
                    document.getElementById('content').classList.remove('hidden');
                }
            })
            .catch(err => {
                console.error('获取IP失败:', err);
                // 获取失败时默认显示拒绝访问
                document.getElementById('content').classList.add('hidden');
                document.getElementById('error').classList.remove('hidden');
            });
    </script>
</body>
</html>
关键注意事项
  • 代理/CDN场景:如果网站用了Nginx、Cloudflare这类代理,一定要配置代理传递真实用户IP给后端,否则REMOTE_ADDR会拿到代理服务器的IP,导致校验失效。
  • 白名单维护:不要把IP白名单硬编码在代码里,最好放在单独的配置文件或数据库中,方便后续动态添加/删除IP。
  • 安全性:永远不要信任前端传来的任何信息,所有权限校验逻辑必须放在后端,前端只是给用户做体验优化。

内容的提问来源于stack exchange,提问作者Voldemort's Wrath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:49:47