feat(auth): 完善API网关JWT认证和权限控制功能

- 实现网关侧JWT工具类和权限规则匹配器
- 集成JWT认证流程,支持Bearer Token验证
- 添加基于路径和HTTP方法的权限控制机制
- 配置白名单路由规则,优化认证性能
- 更新前端受保护路由组件,实现权限验证
- 添加403禁止访问页面和权限检查逻辑
- 重构登录页面,集成实际认证API调用
- 实现用户信息获取和权限加载功能
- 优化全局异常处理器中的认证错误状态码
- 集成FastJSON2和JJWT依赖库支持
This commit is contained in:
2026-02-06 13:11:08 +08:00
parent 719f54bf2e
commit 056cee11cc
33 changed files with 1462 additions and 89 deletions

View File

@@ -1,20 +1,53 @@
import React from 'react';
import { Navigate, useLocation, Outlet } from 'react-router';
import { useAppSelector } from '@/store/hooks';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { fetchCurrentUser, markInitialized } from '@/store/slices/authSlice';
import {
hasPermission,
resolveDefaultAuthorizedPath,
resolveRequiredPermissionByPath,
} from '@/auth/permissions';
interface ProtectedRouteProps {
children?: React.ReactNode;
}
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => {
const { isAuthenticated } = useAppSelector((state) => state.auth);
const dispatch = useAppDispatch();
const { isAuthenticated, token, initialized, loading, permissions } = useAppSelector(
(state) => state.auth
);
const location = useLocation();
const requiredPermission = resolveRequiredPermissionByPath(location.pathname);
React.useEffect(() => {
if (initialized || loading) {
return;
}
if (!token) {
dispatch(markInitialized());
return;
}
void dispatch(fetchCurrentUser());
}, [dispatch, initialized, loading, token]);
if (!initialized || loading) {
return null;
}
if (!isAuthenticated) {
// Redirect to the login page, but save the current location they were trying to go to
return <Navigate to="/login" state={{ from: location }} replace />;
}
if (!hasPermission(permissions, requiredPermission)) {
const fallbackPath = resolveDefaultAuthorizedPath(permissions);
if (location.pathname === fallbackPath) {
return <Navigate to="/403" replace />;
}
return <Navigate to={fallbackPath} replace />;
}
return children ? <>{children}</> : <Outlet />;
};