本文目录导读:

在 PHP 项目中统一进行接口权限校验拦截,核心思路是使用 中间件 或 事件驱动 模式,在请求到达具体控制器方法之前完成鉴权,以下是几种主流且高效的实现方案:
Laravel 框架(中间件方案)
Laravel 提供了最完善的中间件机制。
1 创建权限中间件
php artisan make:middleware CheckPermission
2 实现校验逻辑
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Route;
class CheckPermission
{
public function handle(Request $request, Closure $next)
{
// 获取当前用户(假设通过 JWT/Session 已认证)
$user = auth()->user();
if (!$user) {
return response()->json(['message' => '未认证'], 401);
}
// 获取当前路由名称
$routeName = Route::currentRouteName();
// 或者使用:$routeName = $request->route()->getName();
// 定义不需要权限检查的路由(白名单)
$whitelist = ['login', 'register', 'forgot-password'];
if (in_array($routeName, $whitelist)) {
return $next($request);
}
// 检查用户权限(可根据业务定制)
if (!$user->hasPermission($routeName)) {
return response()->json([
'message' => '权限不足',
'required_permission' => $routeName
], 403);
}
return $next($request);
}
}
3 注册中间件
在 app/Http/Kernel.php 中注册:
protected $routeMiddleware = [
// ...
'permission' => \App\Http\Middleware\CheckPermission::class,
];
4 应用到路由组
Route::middleware(['auth:api', 'permission'])->group(function () {
Route::get('/users', [UserController::class, 'index'])->name('users.list');
Route::post('/users', [UserController::class, 'store'])->name('users.create');
Route::put('/users/{id}', [UserController::class, 'update'])->name('users.update');
});
ThinkPHP 框架(中间件方案)
1 定义中间件
<?php
namespace app\middleware;
use Closure;
use think\Request;
use think\Response;
class CheckPermission
{
public function handle($request, Closure $next)
{
// 获取当前用户(假设已认证)
$user = $request->user;
if (!$user) {
return Response::create(['message' => '未认证'], 401);
}
// 获取当前控制器和方法
$controller = $request->controller();
$action = $request->action();
$permissionKey = "{$controller}@{$action}";
// 定义白名单
$whitelist = ['Index@login', 'Index@register'];
if (in_array($permissionKey, $whitelist)) {
return $next($request);
}
// 权限检查
if (!$user->can($permissionKey)) {
return Response::create(['message' => '权限不足'], 403);
}
return $next($request);
}
}
2 注册中间件
在 config/middleware.php 中:
return [
'CheckPermission' => app\middleware\CheckPermission::class,
];
3 应用到路由
Route::group(['middleware' => ['auth', 'CheckPermission']], function () {
Route::get('users', 'User/index');
Route::post('users', 'User/create');
});
原生 PHP 实现(全局拦截器)
如果不使用框架,可以创建一个统一的入口文件:
<?php
// index.php - 统一入口
require_once 'config.php';
require_once 'auth.php';
class Router {
public static function handle() {
$uri = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
// 路由解析
$route = self::parseRoute($uri, $method);
// 权限校验
if (!self::checkPermission($route)) {
http_response_code(403);
echo json_encode(['message' => '权限不足']);
exit;
}
// 执行控制器
$controller = new $route['controller']();
$action = $route['action'];
echo $controller->$action();
}
private static function checkPermission($route) {
// 白名单
$whitelist = [
['controller' => 'AuthController', 'action' => 'login'],
['controller' => 'AuthController', 'action' => 'register'],
];
foreach ($whitelist as $item) {
if ($item['controller'] == $route['controller'] &&
$item['action'] == $route['action']) {
return true;
}
}
// JWT 验证用户
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
$user = validateJWT($token);
if (!$user) {
return false;
}
// 检查权限
return $user->hasPermission($route['controller'], $route['action']);
}
}
Router::handle();
权限管理核心设计
1 权限存储结构
-- 用户-角色-权限 多对多关系
CREATE TABLE permissions (
id INT PRIMARY KEY,
name VARCHAR(100) UNIQUE, -- 'users.list', 'users.create'
display_name VARCHAR(200),
description TEXT
);
CREATE TABLE roles (
id INT PRIMARY KEY,
name VARCHAR(100) UNIQUE,
display_name VARCHAR(200)
);
CREATE TABLE role_permission (
role_id INT,
permission_id INT,
PRIMARY KEY (role_id, permission_id)
);
CREATE TABLE user_role (
user_id INT,
role_id INT,
PRIMARY KEY (user_id, role_id)
);
2 权限检查逻辑示例
class User {
public function hasPermission($permissionName) {
// 超级管理员拥有所有权限
if ($this->is_super_admin) {
return true;
}
$roles = $this->roles()->with('permissions')->get();
foreach ($roles as $role) {
foreach ($role->permissions as $permission) {
if ($permission->name === $permissionName) {
return true;
}
}
}
return false;
}
}
最佳实践建议
1 注解方式(适用于大型项目)
// Laravel 扩展
#[Permission('users.create')]
public function store(Request $request) {
// ...
}
2 缓存优化
// 使用 Redis 缓存用户权限
class UserPermissionCache {
public function hasPermission($userId, $permissionName) {
$key = "user_permissions:{$userId}";
// 检查缓存
if (Cache::has($key)) {
$permissions = Cache::get($key);
return in_array($permissionName, $permissions);
}
// 从数据库加载并缓存(缓存1小时)
$user = User::find($userId);
$permissions = $user->getAllPermissions()->pluck('name')->toArray();
Cache::put($key, $permissions, 3600);
return in_array($permissionName, $permissions);
}
}
3 日志记录
// 在中间件中记录权限检查日志
Log::channel('permission')->info('权限检查', [
'user_id' => $user->id,
'route' => $routeName,
'result' => $hasPermission ? '通过' : '拒绝',
'ip' => $request->ip(),
'time' => now()
]);
接口权限粒度设计
建议采用三级管控:
- 路由级别:控制能否访问某个接口
- 数据级别:控制能看到哪些数据(自己的/部门的/全部的)
- 字段级别:控制能查看/修改哪些字段
示例:
// 数据权限中间件
class DataPermissionMiddleware {
public function handle($request, $next) {
// 获取用户
$user = auth()->user();
// 根据角色决定数据范围
switch ($user->data_scope) {
case 'self':
// 只返回自己的数据
$request->merge(['user_filter' => $user->id]);
break;
case 'department':
// 返回部门数据
$request->merge(['department_filter' => $user->department_id]);
break;
case 'all':
// 返回所有数据
break;
}
return $next($request);
}
}
选择方案时需要考虑:
- 小项目:使用原生 PHP 的全局拦截器
- 中型项目:ThinkPHP/Laravel 的中间件
- 大型分布式:API 网关(如 Kong)+ 微服务中间件
- 性能敏感:配合缓存(Redis)+ 预编译权限位运算
无论哪种方案,核心思想都是:在请求进入业务逻辑之前,通过统一的拦截点完成身份验证和权限校验。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播