feat: 系统监控后端返回403停止请求;修改请求Token;添加文档

This commit is contained in:
bunny 2025-04-30 17:49:05 +08:00
parent def95eaf16
commit c333355296
10 changed files with 91 additions and 38 deletions

View File

@ -38,8 +38,6 @@
## ✨ v4.0.0 重大更新
新分支`sysn_6.0.0`与上游【Pure Admin】合并旧版放在`master-v1`中,最新的`sysn_6.0.0`放在`dev`中。
### 核心改进
- **全面重构**后端接口、实体类等重构前端重构部分j+优化操作体验
@ -77,10 +75,10 @@
通过 `WebSecurityConfig` 配置
| 路径类型 | 示例 | 访问要求 | 配置方式 |
|------|-------------------|------|--------------------|
| 路径类型 | 示例 | 访问要求 | 配置方式 |
| -------- | ----------------- | -------- | ------------------------- |
| 公开接口 | `/api/public/**` | 无需认证 | 路径包含 `public` 关键字 |
| 私有接口 | `/api/private/**` | 需登录 | 路径包含 `private` 关键字 |
| 私有接口 | `/api/private/**` | 需登录 | 路径包含 `private` 关键字 |
### 路径匹配策略
@ -94,6 +92,21 @@ http.authorizeHttpRequests(auth -> auth
);
```
### Maven工程结构
```mermaid
graph TD
父工程 -->|主项目| auth-api
父工程 -->|代码生成器| generator-code
auth-api -->|启动项、控制器| service
service -->|mapper| dao
service -->|包含domain、配置等| auth-core
dao -->|包含domain、配置等| auth-code
```
## 🛠️ 应用场景
### 1. 纯前端控制模式
@ -144,10 +157,10 @@ http.authorizeHttpRequests(auth -> auth
AntPath详情https://juejin.cn/spost/7498247273660743732
| 模式 | 示例 | 说明 |
|------|-----------------|------------|
| 模式 | 示例 | 说明 |
| -------- | --------------- | ---------------- |
| 精确匹配 | `/api/user` | 完全匹配路径 |
| 通配符 | `/api/user/*` | 匹配单级路径 |
| 通配符 | `/api/user/*` | 匹配单级路径 |
| 多级通配 | `/api/user/**` | 匹配多级路径 |
| 方法限定 | `GET /api/user` | 匹配特定HTTP方法 |
@ -188,13 +201,12 @@ docker compose up -d
```
2. **权限码设计**
- 模块::操作 (如 `user::create`)
- 分层级设计 (如 `system:user:update`)
- 模块::操作 (如 `user::create`)
- 分层级设计 (如 `system:user:update`)
3. **批量操作**
- 使用 Excel/JSON 管理大量权限配置
- 定期备份权限配置
- 使用 Excel/JSON 管理大量权限配置
- 定期备份权限配置
## 🌟 项目优势
@ -217,30 +229,33 @@ docker compose up -d
- [ ] 用户设置持久化存储到数据库
- [ ] 权限弹窗页面优化
- [ ] 后端文档注释完善
- [ ] 系统监控后端返回403停止请求
- [x] 系统监控后端返回403停止请求
- [ ] 优化用户配置权限逻辑,配置后热更新逻辑等
- [ ] 完善后端注释有需要添加ReadMe文档
- [ ] Redis中获取活跃用户
## 前后端接口规范
### 前端示例规范
| **操作** | **API 层** | **Pinia 层** |
|:-------|:--------------|:----------------|
| 查询单个 | `getUser` | `loadUser` |
| 查询列表 | `getUserList` | `loadUserList` |
| 分页查询 | `getUserPage` | `fetchUserPage` |
| 新增数据 | `createUser` | `addUser` |
| 更新数据 | `updateUser` | `editUser` |
| 删除数据 | `deleteUser` | `removeUser` |
| **操作** | **API 层** | **Pinia 层** |
| :------- | :------------ | :-------------- |
| 查询单个 | `getUser` | `loadUser` |
| 查询列表 | `getUserList` | `loadUserList` |
| 分页查询 | `getUserPage` | `fetchUserPage` |
| 新增数据 | `createUser` | `addUser` |
| 更新数据 | `updateUser` | `editUser` |
| 删除数据 | `deleteUser` | `removeUser` |
### 后端接口示例规范
遵循Restful
| **操作** | **RESTful** |
|:-------|:----------------------------|
| 查询列表 | `GET /users` |
| 分页查询 | `GET /users/{page}/{limit}` |
| 查询单个 | `GET /users/{id}` |
| :------- | :-------------------------- |
| 查询列表 | `GET /users` |
| 分页查询 | `GET /users/{page}/{limit}` |
| 查询单个 | `GET /users/{id}` |
| 新增 | `POST /users` |
| 更新 | `PUT /users/{id}` |
| 删除 | `DELETE /users/{id}` |

View File

@ -56,7 +56,7 @@ onMounted(() => {
setI18n();
});
onBeforeMount(() => {
onBeforeMount(async () => {
const { version, name: title } = __APP_INFO__.pkg;
const { VITE_PUBLIC_PATH, MODE } = import.meta.env;
// https://github.com/guMcrey/version-rocket/blob/main/README.zh-CN.md#api

View File

@ -24,7 +24,7 @@ class PureHttp {
private static retryOriginalRequest(config: PureHttpRequestConfig) {
return new Promise((resolve) => {
PureHttp.requests.push((token: string) => {
config.headers['token'] = formatToken(token);
config.headers['Authorization'] = formatToken(token);
resolve(config);
});
});

View File

@ -26,7 +26,8 @@ class PureHttp {
private static retryOriginalRequest(config: PureHttpRequestConfig) {
return new Promise((resolve) => {
PureHttp.requests.push((token: string) => {
config.headers['token'] = formatToken(token);
// TODO Authorization
config.headers['Authorization'] = formatToken(token);
resolve(config);
});
});
@ -97,7 +98,8 @@ class PureHttp {
.then((res: any) => {
// 从结果中获取token
const token = res.data.token;
config.headers['token'] = formatToken(token);
// TODO Authorization
config.headers['Authorization'] = formatToken(token);
PureHttp.requests.forEach((cb) => cb(token));
PureHttp.requests = [];
})
@ -107,7 +109,8 @@ class PureHttp {
}
resolve(PureHttp.retryOriginalRequest(config));
} else {
config.headers['token'] = formatToken(data.token);
// TODO Authorization
config.headers['Authorization'] = formatToken(data.token);
resolve(config);
}
} else {

View File

@ -105,7 +105,7 @@ export function removeToken() {
/** 格式化tokenjwt格式 */
export const formatToken = (token: string): string => {
return token;
return `Bearer ${token}`;
};
/** 是否有按钮级别的权限(根据登录接口返回的`permissions`字段进行判断)*/

View File

@ -21,7 +21,8 @@ editorConfig.MENU_CONF['uploadImage'] = {
//
allowedFileTypes: ['image/png', 'image/jpg', 'image/jpeg'],
meta: { type: 'message' },
headers: { token: token.value },
// TODO Authorization
headers: { Authorization: token.value },
//
customInsert(res: any, insertFn) {
// res.data.url

View File

@ -20,7 +20,8 @@ editorConfig.MENU_CONF['uploadImage'] = {
//
allowedFileTypes: ['image/png', 'image/jpg', 'image/jpeg'],
meta: { type: 'message' },
headers: { token: token.value },
// TODO Authorization
headers: { Authorization: token.value },
//
customInsert(res: any, insertFn) {
// res.data.url

View File

@ -8,6 +8,7 @@ import { useIntervalFn } from '@vueuse/core';
import dayjs from 'dayjs';
import { fetchSystemCPU } from '@/api/v1/actuator';
import SystemCardItem from '@/components/ReCol/SystemCardItem.vue';
import { message } from '@/utils/message';
const cupECharts = ref();
const myChart = ref<any>();
@ -18,6 +19,8 @@ const xSeriesData = ref([]);
//
const dateDisplayLength = ref(20);
const hasAuthority = ref(true);
const option = reactive<UtilsEChartsOption>({
tooltip: {
trigger: 'axis',
@ -71,6 +74,18 @@ const onSearch = async () => {
//
const result = await fetchSystemCPU();
// i
if (result.code) {
if (result.code == 403) {
hasAuthority.value = false;
message('Access Denied');
}
if (result.code != 200) {
hasAuthority.value = false;
}
}
const measurement = result.measurements[0];
if (measurement) {
const value = measurement.value;
@ -91,8 +106,8 @@ onMounted(() => {
onSearch();
//
useIntervalFn(() => onSearch(), 2000);
//
useIntervalFn(() => hasAuthority.value && onSearch(), 2000);
});
</script>

View File

@ -8,6 +8,7 @@ import { useIntervalFn } from '@vueuse/core';
import dayjs from 'dayjs';
import { fetchSystemProcessCPU } from '@/api/v1/actuator';
import SystemCardItem from '@/components/ReCol/SystemCardItem.vue';
import { message } from '@/utils/message';
const jvmCPUECharts = ref();
const myChart = ref<any>();
@ -18,6 +19,9 @@ const xSeriesData = ref([]);
//
const dateDisplayLength = ref(20);
// 访
const hasAuthority = ref(true);
const option = reactive<UtilsEChartsOption>({
tooltip: {
trigger: 'axis',
@ -70,6 +74,18 @@ const onSearch = async () => {
//
const result = await fetchSystemProcessCPU();
// i
if (result.code) {
if (result.code == 403) {
hasAuthority.value = false;
message('Access Denied');
}
if (result.code != 200) {
hasAuthority.value = false;
}
}
const measurement = result.measurements[0];
if (measurement) {
const value = measurement.value;
@ -90,8 +106,8 @@ onMounted(() => {
onSearch();
//
useIntervalFn(() => onSearch(), 2000);
//
useIntervalFn(() => hasAuthority.value && onSearch(), 2000);
});
</script>

View File

@ -34,6 +34,7 @@ import Refresh from '~icons/ep/refresh';
import AddFill from '~icons/ri/add-circle-line';
import Upload from '~icons/ri/upload-line';
import PowersToRole from '@/views/system/role/components/powers-to-role.vue';
import { useRouter } from 'vue-router';
defineOptions({ name: 'RoleManger' });
@ -93,6 +94,7 @@ const onUpdateByFile = () => {
},
});
};
const router = useRouter();
onMounted(() => {
onSearch();