PHPAPI权限怎么控制

wen PHP项目 8

本文目录导读:

PHPAPI权限怎么控制

  1. 基于角色的访问控制 (RBAC)
  2. JWT (JSON Web Token) 鉴权
  3. OAuth 2.0 授权框架
  4. 细粒度权限控制 (ACL)
  5. 中间件实现模式
  6. 最佳实践建议

在PHP API开发中,权限控制是一个核心的安全问题,常见的控制方式包括以下几种,从简单到复杂:

基于角色的访问控制 (RBAC)

这是最基础的权限控制方式。

数据库设计

-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE,
    password VARCHAR(255),
    role_id INT
);
-- 角色表
CREATE TABLE roles (
    id INT PRIMARY KEY,
    role_name VARCHAR(50) -- admin, user, guest
);
-- 权限表
CREATE TABLE permissions (
    id INT PRIMARY KEY,
    permission_name VARCHAR(100) -- user.create, user.delete, article.edit
);

PHP实现示例

class ApiAuth {
    private $rolePermissions = [
        'admin' => ['user.create', 'user.delete', 'article.edit', 'article.delete'],
        'editor' => ['article.edit', 'article.create'],
        'user' => ['article.read']
    ];
    public function checkPermission($userId, $requiredPermission) {
        $user = $this->getUser($userId);
        $role = $user['role'];
        if (!isset($this->rolePermissions[$role])) {
            return false;
        }
        return in_array($requiredPermission, $this->rolePermissions[$role]);
    }
}
// 在API路由中使用
$auth = new ApiAuth();
if (!$auth->checkPermission($_GET['user_id'], 'article.edit')) {
    http_response_code(403);
    echo json_encode(['error' => '无权限']);
    exit;
}

JWT (JSON Web Token) 鉴权

这是目前最流行的API权限控制方式。

实现步骤

// 1. 生成JWT Token
use Firebase\JWT\JWT;
class JwtAuth {
    private $secretKey = 'your-secret-key';
    private $algorithm = 'HS256';
    public function generateToken($userData) {
        $payload = [
            'iss' => 'your-domain.com', // 签发者
            'iat' => time(),            // 签发时间
            'exp' => time() + 7200,     // 过期时间2小时
            'user_id' => $userData['id'],
            'role' => $userData['role'],
            'permissions' => $userData['permissions']
        ];
        return JWT::encode($payload, $this->secretKey, $this->algorithm);
    }
    public function validateToken($token) {
        try {
            $decoded = JWT::decode($token, $this->secretKey, [$this->algorithm]);
            return (array) $decoded;
        } catch (Exception $e) {
            return false;
        }
    }
}
// 2. 中间件检查权限
function apiMiddleware($requiredPermission) {
    $headers = getallheaders();
    $token = str_replace('Bearer ', '', $headers['Authorization'] ?? '');
    $jwt = new JwtAuth();
    $userData = $jwt->validateToken($token);
    if (!$userData) {
        http_response_code(401);
        echo json_encode(['error' => '未授权']);
        exit;
    }
    // 检查权限
    if (!in_array($requiredPermission, $userData['permissions'])) {
        http_response_code(403);
        echo json_encode(['error' => '权限不足']);
        exit;
    }
    return $userData;
}
// 3. 在路由中使用
Route::get('/api/articles', function() {
    $userData = apiMiddleware('article.read');
    // 继续处理请求...
});
Route::post('/api/articles', function() {
    $userData = apiMiddleware('article.create');
    // 继续处理请求...
});

OAuth 2.0 授权框架

适用于第三方应用接入的场景。

简化的OAuth实现

class OAuthServer {
    private $clients = [
        'app1' => ['secret' => 'sec123', 'redirect_uri' => 'http://app1.com/callback']
    ];
    // 授权码模式
    public function authorize($clientId, $redirectUri, $scope) {
        // 验证客户端
        if (!isset($this->clients[$clientId])) {
            throw new Exception('无效客户端');
        }
        // 生成授权码
        $authCode = bin2hex(random_bytes(16));
        // 保存授权码到数据库
        $this->saveAuthCode($authCode, $clientId, $scope);
        // 重定向回客户端
        header("Location: {$redirectUri}?code={$authCode}");
    }
    // 换取Access Token
    public function getAccessToken($code, $clientId, $clientSecret) {
        // 验证客户端凭证
        if ($this->clients[$clientId]['secret'] !== $clientSecret) {
            throw new Exception('无效凭证');
        }
        // 验证授权码
        $authData = $this->validateAuthCode($code);
        // 生成Access Token
        $accessToken = bin2hex(random_bytes(32));
        $refreshToken = bin2hex(random_bytes(32));
        return [
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
            'expires_in' => 3600,
            'scope' => $authData['scope']
        ];
    }
}

细粒度权限控制 (ACL)

适用于复杂权限需求。

PHP实现

class AclController {
    private $acl = [];
    public function __construct() {
        // 定义用户资源的权限
        $this->acl = [
            'user_id_1' => [
                'resource_1' => ['read', 'write'],
                'resource_2' => ['read']
            ],
            'user_id_2' => [
                'resource_1' => ['read']
            ]
        ];
    }
    public function checkAccess($userId, $resourceId, $action) {
        if (!isset($this->acl[$userId])) {
            return false;
        }
        if (!isset($this->acl[$userId][$resourceId])) {
            return false;
        }
        return in_array($action, $this->acl[$userId][$resourceId]);
    }
    public function addPermission($userId, $resourceId, $actions) {
        if (!isset($this->acl[$userId])) {
            $this->acl[$userId] = [];
        }
        $this->acl[$userId][$resourceId] = $actions;
    }
}

中间件实现模式

Laravel风格中间件

class PermissionMiddleware {
    private $permissionMap = [
        'GET' => 'read',
        'POST' => 'create',
        'PUT' => 'update',
        'DELETE' => 'delete'
    ];
    public function handle($request, $next) {
        $method = $request->getMethod();
        $resource = $request->getPathInfo();
        $action = $this->permissionMap[$method];
        // 从Token获取用户信息
        $user = $this->getUserFromToken($request);
        if (!$this->hasPermission($user, $resource, $action)) {
            return response()->json([
                'error' => '权限不足',
                'code' => 403
            ], 403);
        }
        return $next($request);
    }
}

最佳实践建议

使用开源库

  • PHP-JWT: firebase/php-jwt
  • OAuth2: thephpleague/oauth2-server
  • ACL: 自行实现或使用 zendframework/zend-permissions-acl

安全注意事项

// 1. 使用HTTPS
// 2. Token存储在header中,不在URL传递
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
// 3. Token定期轮换
if ($token['exp'] < time()) {
    // 刷新token
}
// 4. 记录操作日志
$logger->info("User {id} accessed {resource}", [
    'id' => $userId,
    'resource' => $resource
]);

性能优化

// 1. 缓存权限数据
$cacheKey = "permissions:{$userId}";
$permissions = $cache->get($cacheKey);
if (!$permissions) {
    $permissions = $db->query("SELECT * FROM user_permissions WHERE user_id = ?", [$userId]);
    $cache->set($cacheKey, $permissions, 3600);
}
// 2. 使用Redis存储Token
$redis->set("token:{$accessToken}", json_encode($userData), 3600);

选择哪种方式取决于你的项目规模和安全需求,对小项目使用JWT+RBAC就足够了,大型系统可能需要OAuth2.0或更复杂的权限模型。

抱歉,评论功能暂时关闭!