PHP 怎么PHP 权限中间件

wen PHP项目 3

本文目录导读:

PHP 怎么PHP 权限中间件

  1. 核心原理:前置拦截
  2. 原生 PHP 实现简单示例
  3. 主流框架中的实现方式
  4. 关键设计模式
  5. 最佳实践建议
  6. 示例:一个可复用的通用权限中间件(不依赖框架)

在 PHP 中实现权限中间件(Authorization Middleware),核心思想是在请求进入具体业务逻辑之前进行拦截和校验,下面从基础原理框架集成逐步介绍。


核心原理:前置拦截

权限中间件本质上是一个可调用的类或函数,它:

  1. 接收当前请求的上下文(路由、用户、角色等)
  2. 检查用户是否有权执行该操作
  3. 有权限则 next() 继续,无权限则终止并返回错误
function middleware($request, $next) {
    if (!checkPermission($request->user, $request->route)) {
        return response('Forbidden', 403);
    }
    return $next($request);
}

原生 PHP 实现简单示例

不依赖框架,用最简方式演示:

// auth_middleware.php
function checkPermission($user, $requiredRole) {
    // 假设用户角色存在 session 中
    session_start();
    $userRole = $_SESSION['role'] ?? 'guest';
    $roles = [
        'admin' => ['create', 'edit', 'delete'],
        'editor' => ['create', 'edit'],
        'viewer' => ['view']
    ];
    return in_array($requiredRole, $roles[$userRole] ?? []);
}
// 在路由入口处使用
$route = $_GET['action'] ?? 'view';
if (!checkPermission($_SESSION['user'] ?? null, $route)) {
    http_response_code(403);
    echo json_encode(['error' => 'Forbidden']);
    exit;
}
// 继续执行正常逻辑

主流框架中的实现方式

1 Laravel(最常用)

// 1. 创建中间件
php artisan make:middleware CheckPermission
// 2. 编写逻辑(app/Http/Middleware/CheckPermission.php)
class CheckPermission
{
    public function handle($request, Closure $next, ...$permissions)
    {
        // 获取当前用户(假设已登录)
        $user = $request->user(); 
        foreach ($permissions as $permission) {
            if (!$user->can($permission)) {
                abort(403, '你没有执行此操作的权限');
            }
        }
        return $next($request);
    }
}
// 3. 注册到 Kernel(app/Http/Kernel.php)
protected $routeMiddleware = [
    // ...其他中间件
    'permission' => \App\Http\Middleware\CheckPermission::class,
];
// 4. 在路由中使用
Route::get('/admin/users', function () {
    // ...
})->middleware('permission:manage-users');
// 或者用权限门面
Route::middleware(['auth', 'permission:edit-posts'])->group(function () {
    Route::post('/posts/{id}', [PostController::class, 'update']);
});

2 ThinkPHP 6+

// 1. 创建中间件
php think make:middleware AuthPermission
// 2. 编写(app/middleware/AuthPermission.php)
class AuthPermission
{
    public function handle($request, \Closure $next)
    {
        // 假设已有 Auth 类判断登录
        $user = Auth::user();
        $currentRoute = $request->path();
        if (!$user || !$user->hasPermission($currentRoute)) {
            return redirect('/403')->with('error', '无权限');
        }
        return $next($request);
    }
}
// 3. 注册(config/middleware.php)
return [
    'AuthPermission' => app\middleware\AuthPermission::class,
];
// 4. 在路由或控制器使用
Route::get('admin/users', 'Admin/UserController@index')->middleware('AuthPermission');

3 Symfony(通用模式)

// 使用 AccessDecisionManager
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class PermissionMiddleware
{
    public function __construct(
        private AuthorizationCheckerInterface $authChecker
    ) {}
    public function onKernelController($event)
    {
        $request = $event->getRequest();
        $attributes = $request->attributes;
        // 从路由注解或 YAML 中获取所需权限
        $requiredPermission = $attributes->get('_permission');
        if ($requiredPermission && !$this->authChecker->isGranted($requiredPermission)) {
            throw new AccessDeniedException('权限不足');
        }
    }
}

关键设计模式

角色-权限分离(RBAC 简化版)

class PermissionMiddleware
{
    private array $rolePermissions = [
        'admin'   => ['*'],                          // 全部权限
        'manager' => ['view_report', 'edit_report'],
        'staff'   => ['view_report'],
    ];
    public function handle($user, string $requiredPermission): bool
    {
        $role = $user->role ?? 'guest';
        $permissions = $this->rolePermissions[$role] ?? [];
        // 超级管理员有 * 通配符
        if (in_array('*', $permissions)) return true;
        return in_array($requiredPermission, $permissions);
    }
}

注解式权限(PHP 8 Attributes)

#[Attribute(Attribute::TARGET_METHOD)]
class RequirePermission {
    public function __construct(public string $permission) {}
}
class PostController {
    #[RequirePermission('delete_posts')]
    public function delete(int $id) {
        // ...
    }
}
// 中间件中解析注解
$reflection = new ReflectionMethod($controller, $method);
$attributes = $reflection->getAttributes(RequirePermission::class);
if (!empty($attributes)) {
    $permission = $attributes[0]->newInstance()->permission;
    // 检查权限
}

最佳实践建议

原则 说明
职责单一 中间件只负责检查权限,具体分配逻辑交给其他系统
尽早返回 无权限立即 403,不要浪费后续资源
缓存角色权限 避免每次请求都查数据库(可用 Redis / 本地存储)
支持多种策略 如:白名单(只允许某些IP)、黑名单、动态权限(如资源所有者)
清晰错误提示 区分“未登录”(401)和“无权限”(403)
调试友好 开发环境可记录谁在什么时间请求了什么被拒绝

示例:一个可复用的通用权限中间件(不依赖框架)

interface PermissionChecker {
    public function hasPermission(string $user, string $permission): bool;
}
class SimpleRoleChecker implements PermissionChecker {
    private array $roles;
    public function __construct(array $roles) {
        $this->roles = $roles;
    }
    public function hasPermission(string $userRole, string $permission): bool {
        $perms = $this->roles[$userRole] ?? [];
        return in_array($permission, $perms) || in_array('*', $perms);
    }
}
class PermissionMiddleware {
    private PermissionChecker $checker;
    public function __construct(PermissionChecker $checker) {
        $this->checker = $checker;
    }
    public function handle(callable $next, string $permission): mixed {
        $userRole = $_SESSION['role'] ?? 'guest';
        if (!$this->checker->hasPermission($userRole, $permission)) {
            http_response_code(403);
            return ['error' => 'Forbidden'];
        }
        return $next();
    }
}
// 使用
$roles = [
    'admin' => ['*'],
    'editor' => ['create_post', 'edit_post'],
];
$middleware = new PermissionMiddleware(new SimpleRoleChecker($roles));
$result = $middleware->handle(function() {
    return "正常响应内容";
}, 'create_post');

  • 核心:在请求处理前拦截,检查用户身份与权限
  • 框架:Laravel/ThinkPHP/Symfony 都提供完善的中间件机制
  • 进阶:结合 RBAC、ABAC 模型、注解/属性、策略模式
  • 效率:权限查找尽量使用缓存,减少数据库开销

如果你能提供更具体的场景(如使用哪个框架、权限模型是 RBAC 还是资源级),我可以给出更针对性的代码示例。

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