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

如何不使用htaccess限制Staging子域名访问?(PHP5.6/Apache/CentOS7)

最佳实现方案:基于Apache+PHP+MySQL的预发布环境IP白名单限制

针对你的需求,最佳方案是在Apache层面通过mod_rewrite将所有请求(包括静态资源)转发到一个PHP脚本进行IP校验,这样既能实现MySQL动态IP白名单,又能覆盖所有资源的访问控制——完美解决你之前遇到的静态资源不受限问题。下面是具体的实现步骤:

1. 配置Apache虚拟主机(替代.htaccess)

因为你不想用.htaccess,直接在Apache的虚拟主机配置文件(比如/etc/httpd/conf.d/dev.example.com.conf)中添加规则,确保所有请求先经过IP校验脚本:

<VirtualHost *:80>
    ServerName dev.example.com
    DocumentRoot /var/www/dev.example.com/public

    # 启用mod_rewrite模块(确保已在httpd.conf中开启)
    RewriteEngine On

    # 排除校验脚本本身,避免循环请求
    RewriteCond %{REQUEST_URI} !^/ip-check.php$
    # 将所有请求转发到ip-check.php,携带原请求路径
    RewriteRule ^(.*)$ /ip-check.php?request_uri=$1 [L]
</VirtualHost>

配置完成后重启Apache生效:

systemctl restart httpd

2. 编写IP校验脚本(ip-check.php)

在你的网站根目录创建ip-check.php,负责连接MySQL校验IP、转发合法请求或返回403:

<?php
// 1. 数据库连接配置(根据你的实际信息修改)
$dbHost = 'localhost';
$dbUser = 'your_db_user';
$dbPass = 'your_db_password';
$dbName = 'your_db_name';

$conn = mysqli_connect($dbHost, $dbUser, $dbPass, $dbName);
if (!$conn) {
    die('数据库连接失败: ' . mysqli_connect_error());
}

// 2. 获取用户真实IP(支持反向代理场景)
$userIp = $_SERVER['REMOTE_ADDR'];
// 如果有反向代理,优先取X-Forwarded-For(注意:需确保代理服务器正确设置该头)
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $userIp = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
    $userIp = trim($userIp);
}

// 3. 从MySQL查询IP是否在白名单(假设表名为allowed_ips,字段为ip_address)
$query = "SELECT ip_address FROM allowed_ips WHERE ip_address = ?";
$stmt = mysqli_prepare($conn, $query);
mysqli_stmt_bind_param($stmt, 's', $userIp);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);

if (mysqli_stmt_num_rows($stmt) > 0) {
    // IP合法,转发原请求
    $requestUri = isset($_GET['request_uri']) ? $_GET['request_uri'] : '';
    $filePath = $_SERVER['DOCUMENT_ROOT'] . '/' . $requestUri;

    // 检查目标文件是否存在
    if (file_exists($filePath) && is_file($filePath)) {
        // 返回正确的MIME类型,确保静态资源正常加载
        $mimeType = mime_content_type($filePath);
        header("Content-Type: $mimeType");
        readfile($filePath);
        exit;
    } else {
        // 文件不存在,返回404
        http_response_code(404);
        echo '404 Not Found';
        exit;
    }
} else {
    // IP非法,返回403禁止访问
    http_response_code(403);
    echo '403 Forbidden: 你无权访问该预发布环境';
    exit;
}

// 清理资源
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

3. 性能优化建议

如果预发布环境访问量较大,每次请求都查数据库会影响性能,建议添加缓存机制:

// 新增缓存逻辑:将IP列表缓存到文件,5分钟更新一次
$cacheFile = '/tmp/allowed_ips.cache';
$cacheExpiry = 300; // 缓存有效期(秒)

if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $cacheExpiry) {
    // 从缓存读取IP列表
    $allowedIps = unserialize(file_get_contents($cacheFile));
} else {
    // 从数据库读取并更新缓存
    $query = "SELECT ip_address FROM allowed_ips";
    $result = mysqli_query($conn, $query);
    $allowedIps = [];
    while ($row = mysqli_fetch_assoc($result)) {
        $allowedIps[] = $row['ip_address'];
    }
    file_put_contents($cacheFile, serialize($allowedIps));
}

// 校验IP是否在缓存列表中
if (in_array($userIp, $allowedIps)) {
    // 放行逻辑...
}

为什么这个方案更优?

  • 覆盖所有资源:不管是PHP页面还是图片、JS/CSS静态文件,都会经过IP校验,彻底解决你之前的漏洞
  • 动态更新IP:直接修改MySQL表中的IP即可生效,无需重启Apache或修改配置文件
  • 避免.htaccess:完全符合你不使用.htaccess的要求

内容的提问来源于stack exchange,提问作者TStackOverflow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:14:52