本文目录导读:

在 PHP 中实现白名单授权,通常用于限制某些操作、IP 地址、API 访问或用户权限,以下是几种常见的白名单授权实现方式:
IP 白名单授权
基本 IP 白名单
<?php
class IPWhitelist {
private $whitelist = [
'192.168.1.100',
'10.0.0.1',
'127.0.0.1'
];
public function checkIP($ip = null) {
if ($ip === null) {
$ip = $_SERVER['REMOTE_ADDR'];
}
if (in_array($ip, $this->whitelist)) {
return true;
}
// 支持 CIDR 格式
foreach ($this->whitelist as $allowed) {
if (strpos($allowed, '/') !== false) {
if ($this->ipInCIDR($ip, $allowed)) {
return true;
}
}
}
return false;
}
private function ipInCIDR($ip, $cidr) {
list($subnet, $bits) = explode('/', $cidr);
$ip = ip2long($ip);
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
$subnet &= $mask;
return ($ip & $mask) === $subnet;
}
}
// 使用示例
$whitelist = new IPWhitelist();
if (!$whitelist->checkIP()) {
header('HTTP/1.1 403 Forbidden');
die('Access denied');
}
API 密钥白名单
<?php
class APIKeyAuth {
private $apiKeys = [
'key_1234567890' => [
'name' => 'Application A',
'permissions' => ['read', 'write']
],
'key_0987654321' => [
'name' => 'Application B',
'permissions' => ['read']
]
];
public function authenticate($apiKey) {
if (isset($this->apiKeys[$apiKey])) {
$_SESSION['api_client'] = $this->apiKeys[$apiKey];
return true;
}
return false;
}
public function checkPermission($permission) {
if (!isset($_SESSION['api_client'])) {
return false;
}
return in_array($permission, $_SESSION['api_client']['permissions']);
}
}
// 使用示例
$auth = new APIKeyAuth();
$apiKey = $_GET['api_key'] ?? $_SERVER['HTTP_X_API_KEY'] ?? null;
if (!$apiKey || !$auth->authenticate($apiKey)) {
header('HTTP/1.1 401 Unauthorized');
echo json_encode(['error' => 'Invalid API key']);
exit;
}
数据库驱动的用户白名单
<?php
class UserWhitelist {
private $db;
public function __construct($dbConnection) {
$this->db = $dbConnection;
}
public function isUserAuthorized($userId, $resource) {
$stmt = $this->db->prepare("
SELECT 1 FROM user_whitelist
WHERE user_id = ? AND resource = ? AND status = 'active'
LIMIT 1
");
$stmt->execute([$userId, $resource]);
return $stmt->fetchColumn() !== false;
}
public function addToWhitelist($userId, $resource) {
$stmt = $this->db->prepare("
INSERT INTO user_whitelist (user_id, resource, status, created_at)
VALUES (?, ?, 'active', NOW())
ON DUPLICATE KEY UPDATE status = 'active'
");
return $stmt->execute([$userId, $resource]);
}
public function removeFromWhitelist($userId, $resource) {
$stmt = $this->db->prepare("
UPDATE user_whitelist
SET status = 'removed'
WHERE user_id = ? AND resource = ?
");
return $stmt->execute([$userId, $resource]);
}
}
// 数据库表结构
/*
CREATE TABLE user_whitelist (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
resource VARCHAR(255) NOT NULL,
status ENUM('active', 'removed') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_user_resource (user_id, resource)
);
*/
配置文件白名单
<?php
// config/whitelist.php
return [
'controllers' => [
'allowed' => [
'HomeController',
'UserController',
'ProductController'
],
'denied' => [
'AdminController' // 需要额外授权
]
],
'actions' => [
'public' => ['login', 'register', 'forgot_password'],
'authorized' => ['profile', 'settings', 'orders']
],
'ip_ranges' => [
'127.0.0.1',
'192.168.0.0/16',
'10.0.0.0/8'
]
];
// 使用配置文件
class WhitelistManager {
private $whitelist;
public function __construct() {
$this->whitelist = require 'config/whitelist.php';
}
public function checkControllerAccess($controller) {
return in_array($controller, $this->whitelist['controllers']['allowed']);
}
public function checkIPAccess($ip) {
foreach ($this->whitelist['ip_ranges'] as $range) {
if (strpos($range, '/') !== false) {
list($subnet, $bits) = explode('/', $range);
if ($this->ipInRange($ip, $subnet, $bits)) {
return true;
}
} else if ($ip === $range) {
return true;
}
}
return false;
}
private function ipInRange($ip, $subnet, $bits) {
$ip = ip2long($ip);
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
$subnet &= $mask;
return ($ip & $mask) === $subnet;
}
}
中间件形式的白名单授权
<?php
class WhitelistMiddleware {
public function handle($request, $next) {
// 检查 IP 白名单
if (!$this->checkIPWhitelist()) {
return $this->denyAccess('IP not authorized');
}
// 检查 API 密钥
if (!$this->checkAPIKey()) {
return $this->denyAccess('Invalid API key');
}
// 检查用户权限
if (!$this->checkUserPermissions()) {
return $this->denyAccess('Insufficient permissions');
}
return $next($request);
}
private function checkIPWhitelist() {
$whitelist = ['192.168.1.0/24', '10.0.0.1'];
$clientIP = $_SERVER['REMOTE_ADDR'];
foreach ($whitelist as $allowed) {
if (strpos($allowed, '/') !== false) {
if ($this->ipInCIDR($clientIP, $allowed)) {
return true;
}
} else if ($clientIP === $allowed) {
return true;
}
}
return false;
}
private function checkAPIKey() {
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? null;
$validKeys = ['prod_key_2024', 'dev_key_2024'];
return in_array($apiKey, $validKeys);
}
private function checkUserPermissions() {
// 根据具体业务逻辑实现
return true;
}
private function denyAccess($message) {
header('HTTP/1.1 403 Forbidden');
echo json_encode(['error' => $message]);
exit;
}
}
完整示例:多因素白名单授权系统
<?php
class MultiFactorWhitelist {
private $rules = [
'ip' => [
'whitelist' => ['127.0.0.1', '::1'],
'strict' => true
],
'time' => [
'start' => '09:00',
'end' => '18:00',
'timezone' => 'Asia/Shanghai'
],
'user_agent' => [
'allowed' => ['Mozilla/5.0', 'curl/7.68.0'],
'block_bots' => true
],
'request_rate' => [
'max_requests' => 100,
'per_minutes' => 1
]
];
public function authorize() {
// IP 白名单检查
if ($this->rules['ip']['strict']) {
if (!$this->checkIP()) {
return $this->deny('IP not in whitelist');
}
}
// 时间窗口检查
if (!$this->checkTimeWindow()) {
return $this->deny('Access outside allowed time');
}
// User-Agent 检查
if (!$this->checkUserAgent()) {
return $this->deny('Invalid user agent');
}
// 请求频率检查
if (!$this->checkRateLimit()) {
return $this->deny('Rate limit exceeded');
}
return true;
}
private function checkIP() {
$clientIP = $_SERVER['REMOTE_ADDR'];
return in_array($clientIP, $this->rules['ip']['whitelist']);
}
private function checkTimeWindow() {
$now = new DateTime('now', new DateTimeZone($this->rules['time']['timezone']));
$start = new DateTime($this->rules['time']['start']);
$end = new DateTime($this->rules['time']['end']);
return $now >= $start && $now <= $end;
}
private function checkUserAgent() {
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if ($this->rules['user_agent']['block_bots']) {
$botPatterns = ['bot', 'crawler', 'spider', 'scrape'];
foreach ($botPatterns as $pattern) {
if (stripos($userAgent, $pattern) !== false) {
return false;
}
}
}
if (!empty($this->rules['user_agent']['allowed'])) {
foreach ($this->rules['user_agent']['allowed'] as $allowed) {
if (stripos($userAgent, $allowed) !== false) {
return true;
}
}
return false;
}
return true;
}
private function checkRateLimit() {
// 实现基于 Redis 或文件的速率限制
return true;
}
private function deny($reason) {
error_log("Access denied: $reason from IP: " . $_SERVER['REMOTE_ADDR']);
header('HTTP/1.1 403 Forbidden');
die(json_encode(['error' => 'Access denied']));
}
}
// 使用示例
$auth = new MultiFactorWhitelist();
$auth->authorize();
最佳实践建议
-
安全性考虑:
- 永远不要在客户端存储白名单
- 使用 HTTPS 传输敏感信息
- 定期更新和审查白名单
- 记录所有授权失败的尝试
-
性能优化:
- 使用缓存(Redis/Memcached)存储白名单
- 对于数据库驱动的白名单,确保有适当的索引
- 考虑使用 Bloom Filter 进行大规模白名单检查
-
日志和监控:
- 记录所有授权决策
- 监控异常访问模式
- 设置告警机制
-
灵活性:
- 支持动态更新白名单而无需重启服务
- 提供管理界面来管理白名单
- 支持白名单的分组和继承
根据你的具体需求选择合适的方式,或者组合使用多种方式来实现更完善的白名单授权系统。