如何制作仅允许特定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
相关产品推荐
相关产品推荐

