154 lines
4.2 KiB
Markdown
154 lines
4.2 KiB
Markdown
|
|
# 任务013:严重问题修复
|
|||
|
|
|
|||
|
|
## 目标
|
|||
|
|
|
|||
|
|
修复全面代码审查发现的5个严重问题。
|
|||
|
|
|
|||
|
|
## 修复清单
|
|||
|
|
|
|||
|
|
### 1. 设备指令接口权限校验( 高优先级)
|
|||
|
|
|
|||
|
|
**位置:** `src/tcp/commands.rs`
|
|||
|
|
|
|||
|
|
**问题:** HTTP API接口缺少权限校验,任何登录用户都能控制设备。
|
|||
|
|
|
|||
|
|
**修复方案:**
|
|||
|
|
```rust
|
|||
|
|
// 修改 send_command handler
|
|||
|
|
pub async fn send_command(
|
|||
|
|
user: CurrentUser, // 新增
|
|||
|
|
State(state): State<AppState>,
|
|||
|
|
Path(dev_id): Path<String>,
|
|||
|
|
Json(body): Json<CommandRequest>,
|
|||
|
|
) -> Result<Json<Value>, AppError> {
|
|||
|
|
auth::check_permission(&user, "device:operate")?; // 新增
|
|||
|
|
// ... 原有逻辑
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修改 get_online_devices handler
|
|||
|
|
pub async fn get_online_devices(
|
|||
|
|
user: CurrentUser, // 新增
|
|||
|
|
State(state): State<AppState>,
|
|||
|
|
) -> Result<Json<Value>, AppError> {
|
|||
|
|
auth::check_permission(&user, "device:view")?; // 新增
|
|||
|
|
// ... 原有逻辑
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 组织树接口权限校验和数据隔离(🔴 高优先级)
|
|||
|
|
|
|||
|
|
**位置:** `src/routes/cabinet_tree.rs`
|
|||
|
|
|
|||
|
|
**问题:** 组织树接口无权限校验,且未做数据隔离,用户能看到所有组织的数据。
|
|||
|
|
|
|||
|
|
**修复方案:**
|
|||
|
|
```rust
|
|||
|
|
pub async fn get_organization_tree(
|
|||
|
|
user: CurrentUser, // 新增
|
|||
|
|
State(state): State<AppState>,
|
|||
|
|
) -> Result<Json<Value>, AppError> {
|
|||
|
|
auth::check_permission(&user, "device:view")?; // 新增
|
|||
|
|
|
|||
|
|
let db = &state.mysql;
|
|||
|
|
|
|||
|
|
// 根据角色过滤数据
|
|||
|
|
let orgs = if user.role_level >= 2 {
|
|||
|
|
// 总管理员看所有组织
|
|||
|
|
sqlx::query_as::<_, OrganizationRow>("SELECT id, name FROM organizations ORDER BY id")
|
|||
|
|
.fetch_all(db)
|
|||
|
|
.await?
|
|||
|
|
} else if let Some(org_id) = user.organization_id {
|
|||
|
|
// 企业管理员只看本组织
|
|||
|
|
sqlx::query_as::<_, OrganizationRow>(
|
|||
|
|
"SELECT id, name FROM organizations WHERE id = ? ORDER BY id"
|
|||
|
|
)
|
|||
|
|
.bind(org_id)
|
|||
|
|
.fetch_all(db)
|
|||
|
|
.await?
|
|||
|
|
} else {
|
|||
|
|
vec![] // 无组织用户看不到数据
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ... 构建树状结构
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 默认密码硬编码(🔴 中优先级)
|
|||
|
|
|
|||
|
|
**位置:** `src/routes/users.rs`
|
|||
|
|
|
|||
|
|
**问题:** 默认密码 "123456" 硬编码在代码中。
|
|||
|
|
|
|||
|
|
**修复方案:**
|
|||
|
|
```rust
|
|||
|
|
// config.rs 添加默认密码配置
|
|||
|
|
pub const DEFAULT_PASSWORD: &str = "123456"; // 或从环境变量读取
|
|||
|
|
|
|||
|
|
// users.rs 使用配置
|
|||
|
|
use crate::config::DEFAULT_PASSWORD;
|
|||
|
|
|
|||
|
|
// 创建用户时
|
|||
|
|
let password = body.password.unwrap_or_else(|| DEFAULT_PASSWORD.to_string());
|
|||
|
|
let hashed = auth::hash_password(&password)?;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. auth_str安全码明文打印到日志(🔴 中优先级)
|
|||
|
|
|
|||
|
|
**位置:** `src/routes/organizations.rs` 或 `src/tcp/handler.rs`
|
|||
|
|
|
|||
|
|
**问题:** auth_str安全码明文打印到日志,存在泄露风险。
|
|||
|
|
|
|||
|
|
**修复方案:**
|
|||
|
|
```rust
|
|||
|
|
// 修改日志输出,只打印前2位+***
|
|||
|
|
tracing::info!(
|
|||
|
|
"生成安全码 id={} auth_str={}***",
|
|||
|
|
id,
|
|||
|
|
&auth_str[..2]
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 或完全不打印auth_str
|
|||
|
|
tracing::info!("生成安全码 id={}", id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 前端刷新后用户信息丢失(🔴 中优先级)
|
|||
|
|
|
|||
|
|
**位置:** `src/stores/auth.ts` 或 `src/App.tsx`
|
|||
|
|
|
|||
|
|
**问题:** 页面刷新后,虽然token在localStorage,但用户信息(permissions等)未恢复,导致权限按钮消失。
|
|||
|
|
|
|||
|
|
**修复方案:**
|
|||
|
|
```tsx
|
|||
|
|
// stores/auth.ts 添加 restore 方法
|
|||
|
|
const restoreAuth = async () => {
|
|||
|
|
const token = localStorage.getItem('token');
|
|||
|
|
if (!token) return false;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const user = await api.get('/auth/me');
|
|||
|
|
setToken(token);
|
|||
|
|
setUser(user);
|
|||
|
|
setPermissions(user.permissions);
|
|||
|
|
return true;
|
|||
|
|
} catch {
|
|||
|
|
localStorage.removeItem('token');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// App.tsx 或 AdminLayout.tsx 中调用
|
|||
|
|
useEffect(() => {
|
|||
|
|
restoreAuth();
|
|||
|
|
}, []);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 质量约束
|
|||
|
|
|
|||
|
|
1. 完成代码后执行 `cargo check` + `cargo clippy` + `tsc --noEmit`,零报错零警告
|
|||
|
|
2. 分层拆分,单函数≤80行,命名语义化,完整注释
|
|||
|
|
3. 所有外部IO/网络请求异常捕获,禁止裸panic
|
|||
|
|
4. 分支逻辑全覆盖,不遗漏兜底分支
|
|||
|
|
5. 常量抽离,不使用废弃API
|
|||
|
|
6. Rust内存安全,React函数组件+Hooks
|
|||
|
|
7. 修复后重新运行审查清单中的安全项目,确保全部通过
|