本文目录导读:

在 PHP 中实现权限中间件(Authorization Middleware),核心思想是在请求进入具体业务逻辑之前进行拦截和校验,下面从基础原理到框架集成逐步介绍。
核心原理:前置拦截
权限中间件本质上是一个可调用的类或函数,它:
- 接收当前请求的上下文(路由、用户、角色等)
- 检查用户是否有权执行该操作
- 有权限则
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 还是资源级),我可以给出更针对性的代码示例。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播