mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
- 创建用户表(users)包含基本信息和认证字段 - 创建角色表(roles)用于权限控制 - 创建权限表(permissions)定义系统权限 - 创建用户角色关联表(user_roles)建立用户与角色关系 - 创建角色权限关联表(role_permissions)建立角色与权限关系 - 创建迁移记录表(migrations)追踪数据库变更 - 添加AdminController提供管理员面板功能 - 实现系统监控、配置管理、缓存清理等功能 - 添加AOP切面编程支持的各种通知类型 - 实现告警管理AlertManager支持多渠道告警 - 添加文档注解接口规范
164 lines
4.1 KiB
PHP
164 lines
4.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Interceptor;
|
|
|
|
use Fendx\Core\Aop\JoinPoint;
|
|
use Fendx\Core\Aop\Advice\AroundAdvice;
|
|
use Fendx\Web\Request\Request;
|
|
use Fendx\Web\Response\HttpResponse;
|
|
use Fendx\Security\Auth\JwtManager;
|
|
|
|
/**
|
|
* 认证拦截器
|
|
*/
|
|
class AuthInterceptor implements AroundAdvice
|
|
{
|
|
private JwtManager $jwtManager;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->jwtManager = new JwtManager([
|
|
'secret_key' => config('jwt.secret_key', 'your-secret-key'),
|
|
'algorithm' => config('jwt.algorithm', 'HS256'),
|
|
'expires_in' => config('jwt.expires_in', 3600),
|
|
]);
|
|
}
|
|
|
|
public function invoke(JoinPoint $joinPoint): mixed
|
|
{
|
|
$request = $this->getRequest();
|
|
|
|
// 检查是否需要认证
|
|
if ($this->isPublicRoute($request)) {
|
|
return $joinPoint->proceed();
|
|
}
|
|
|
|
// 获取令牌
|
|
$token = $this->extractToken($request);
|
|
|
|
if (!$token) {
|
|
return $this->unauthorizedResponse('Missing authentication token');
|
|
}
|
|
|
|
// 验证令牌
|
|
try {
|
|
$payload = $this->jwtManager->validateToken($token);
|
|
} catch (\Exception $e) {
|
|
return $this->unauthorizedResponse('Invalid or expired token');
|
|
}
|
|
|
|
// 设置用户信息到上下文
|
|
$this->setUserContext($payload);
|
|
|
|
return $joinPoint->proceed();
|
|
}
|
|
|
|
/**
|
|
* 获取当前请求对象
|
|
*/
|
|
private function getRequest(): Request
|
|
{
|
|
return Request::createFromGlobals();
|
|
}
|
|
|
|
/**
|
|
* 检查是否为公开路由
|
|
*/
|
|
private function isPublicRoute(Request $request): bool
|
|
{
|
|
$path = $request->path();
|
|
$method = $request->method();
|
|
|
|
$publicRoutes = [
|
|
// 登录相关
|
|
'POST:/api/auth/login',
|
|
'POST:/api/auth/register',
|
|
'POST:/api/auth/refresh',
|
|
|
|
// 公开API
|
|
'GET:/api/health',
|
|
'GET:/api/version',
|
|
|
|
// 静态资源
|
|
'GET:/',
|
|
'GET:/favicon.ico',
|
|
];
|
|
|
|
$currentRoute = "{$method}:{$path}";
|
|
|
|
// 精确匹配
|
|
if (in_array($currentRoute, $publicRoutes)) {
|
|
return true;
|
|
}
|
|
|
|
// 模糊匹配
|
|
foreach ($publicRoutes as $route) {
|
|
if (str_ends_with($route, '*')) {
|
|
$prefix = substr($route, 0, -1);
|
|
if (str_starts_with($currentRoute, $prefix)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 从请求中提取令牌
|
|
*/
|
|
private function extractToken(Request $request): ?string
|
|
{
|
|
// 从Authorization头获取
|
|
$authHeader = $request->header('Authorization');
|
|
if ($authHeader) {
|
|
$token = $this->jwtManager->extractTokenFromHeader($authHeader);
|
|
if ($token) {
|
|
return $token;
|
|
}
|
|
}
|
|
|
|
// 从Cookie获取
|
|
$token = $request->cookie('token');
|
|
if ($token) {
|
|
return $token;
|
|
}
|
|
|
|
// 从查询参数获取(不推荐,仅用于调试)
|
|
$token = $request->get('token');
|
|
if ($token) {
|
|
return $token;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 设置用户上下文
|
|
*/
|
|
private function setUserContext(array $payload): void
|
|
{
|
|
// 这里应该设置到全局上下文中
|
|
// Context::set('user_id', $payload['user_id']);
|
|
// Context::set('username', $payload['username']);
|
|
// Context::set('roles', $payload['roles'] ?? []);
|
|
// Context::set('permissions', $payload['permissions'] ?? []);
|
|
}
|
|
|
|
/**
|
|
* 返回未授权响应
|
|
*/
|
|
private function unauthorizedResponse(string $message): HttpResponse
|
|
{
|
|
return (new HttpResponse())
|
|
->setStatusCode(401)
|
|
->json([
|
|
'code' => 401,
|
|
'message' => $message,
|
|
'data' => null,
|
|
'trace_id' => \Fendx\Core\Context\Context::getTraceId(),
|
|
]);
|
|
}
|
|
}
|