本文目录导读:

- 方案一:基础开关常量(最简单)
- 方案二:URL 白名单(针对请求路径)
- 方案三:IP 白名单(针对请求来源)
- 方案四:用户角色权限白名单(针对逻辑权限)
- 方案五:配置文件化与缓存(大型项目推荐)
- 方案六:使用中间件(适合框架如 Laravel / ThinkPHP)
在 PHP 中实现白名单开关,通常是指只允许特定条件通过,其他条件一律拒绝,根据你的需求(是验证 URL、请求 IP、用户角色,还是某个功能模块的开关),有以下几种常见的实现方案:
基础开关常量(最简单)
如果你只想控制某个功能是否启用,直接定义一个全局常量或配置文件。
<?php
// config.php
// 设置为 true 则开启,false 则关闭
define('FEATURE_NEW_LOGIN_ENABLED', true);
define('APP_DEBUG', false);
?>
<?php
// 使用示例
if (FEATURE_NEW_LOGIN_ENABLED) {
// 执行新逻辑
echo "新登录逻辑已开启";
} else {
echo "旧登录逻辑";
}
?>
URL 白名单(针对请求路径)
用于 Web 应用入口,只允许访问指定的路径,其他路径直接 404 或跳转。
<?php
$whitelist = [
'/login',
'/register',
'/api/public',
'/home'
];
// 获取当前访问的 URI(假设是 /login?name=xx)
$current_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (!in_array($current_uri, $whitelist, true)) {
http_response_code(404);
exit('页面不存在'); // 或者跳到指定页面
}
// 通过验证,继续执行
echo "欢迎访问: " . $current_uri;
?>
IP 白名单(针对请求来源)
最典型的应用是后台管理接口,只允许特定 IP 访问。
<?php
function checkIpWhitelist(): bool {
// 有效白名单
$allowed_ips = [
'127.0.0.1', // 本机
'192.168.1.100', // 公司内网
'10.0.0.0/8', // 支持 CIDR
'::1' // IPv6 localhost
];
$user_ip = $_SERVER['REMOTE_ADDR'] ?? '';
foreach ($allowed_ips as $ip) {
// 1. 精确匹配
if ($ip === $user_ip) {
return true;
}
// 2. CIDR 匹配
if (strpos($ip, '/') !== false) {
[$subnet, $prefix] = explode('/', $ip);
if (isIpInSubnet($user_ip, $subnet, (int)$prefix)) {
return true;
}
}
}
return false;
}
// 辅助函数:判断 IP 是否在子网内
function isIpInSubnet($ip, $subnet, $prefix) {
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
filter_var($subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$ip_long = ip2long($ip);
$subnet_long = ip2long($subnet);
$mask = -1 << (32 - $prefix);
$subnet_long &= $mask;
return ($ip_long & $mask) === $subnet_long;
}
return false;
}
// 使用
if (!checkIpWhitelist()) {
http_response_code(403); // 禁止访问
exit('Access Denied');
}
?>
用户角色权限白名单(针对逻辑权限)
适用于后台系统,在 if 判断中加入角色验证。
<?php
function getUserRole() {
// 假设从 Session 获取
return $_SESSION['role'] ?? 'guest';
}
// 路由权限白名单映射
$role_whitelist = [
'admin' => ['dashboard', 'settings', 'users', 'delete'],
'editor' => ['dashboard', 'articles'],
'guest' => ['login', 'index'],
];
$current_action = $_GET['action'] ?? 'index';
$user_role = getUserRole();
// 判断当前角色是否拥有这个 action 的权限
if (!isset($role_whitelist[$user_role]) ||
!in_array($current_action, $role_whitelist[$user_role], true)) {
http_response_code(403);
exit('无权限执行此操作');
}
echo "允许执行: $current_action";
?>
配置文件化与缓存(大型项目推荐)
将白名单放到配置文件中(如 config/whitelist.php),并可以针对不同环境区分。
<?php
// config/whitelist.php
return [
'api_keys' => ['abc123xyz', 'def456uvw'],
'urls' => ['/open-api/v1/user'],
'ips' => ['10.0.0.1', '172.16.0.0/16'],
'features' => ['payment' => true, 'export' => false],
];
// 调用处
function checkWhitelist() {
$whitelist = require __DIR__ . '/config/whitelist.php';
// 检查 API Key
$api_key = $_GET['token'] ?? null;
if ($api_key && in_array($api_key, $whitelist['api_keys'], true)) {
return true;
}
// 检查 URL
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (in_array($path, $whitelist['urls'], true)) {
return true;
}
// 检查 IP
$ip = $_SERVER['REMOTE_ADDR'];
if (in_array($ip, $whitelist['ips'], true)) {
return true;
}
return false;
}
?>
使用中间件(适合框架如 Laravel / ThinkPHP)
如果使用框架,通常框架自带“中间件”或“门卫”功能,以 Laravel 为例:
// app/Http/Middleware/CheckWhitelist.php
public function handle($request, Closure $next)
{
$allowed_hosts = ['api.example.com', 'admin.example.com'];
if (!in_array($request->getHost(), $allowed_hosts)) {
abort(403, '非允许的主机');
}
return $next($request);
}
| 需求场景 | 推荐方案 |
|---|---|
| 功能是否开启 | 常量 + if/else |
| 请求路径过滤 | URL 白名单数组 + in_array |
| 访问来源过滤 | IP 白名单 + CIDR 匹配 |
| 用户权限管理 | 角色映射数组 |
| 大型系统 | 配置化 + 中间件 |
⚠️ 注意:
- 如果白名单数据较多,建议不要硬编码在函数里,而是放到配置文件或数据库中。
- 涉及到安全(如 IP 限制),先拒绝后放行,默认拒绝任何未匹配项(
deny by default)。 - 在极端情况下(如防止暴力破解),可以结合缓存(Redis)做动态封禁。