156 lines
4.4 KiB
Markdown
156 lines
4.4 KiB
Markdown
# 任务010:安全修复
|
||
|
||
## 目标
|
||
|
||
修复代码审查发现的4个严重安全问题。
|
||
|
||
## 修复清单
|
||
|
||
### 1. SQL注入修复( 高优先级)
|
||
|
||
**问题位置:**
|
||
- `src/routes/operation_logs.rs:49-63`
|
||
- `src/routes/charge_records.rs:130`
|
||
- `src/routes/energy_stats.rs:341`
|
||
|
||
**修复方案:**
|
||
将所有 `format!` 拼接的SQL改为参数化查询。
|
||
|
||
```rust
|
||
// 错误示例(operation_logs.rs)
|
||
let sql = format!(
|
||
"SELECT * FROM operation_logs WHERE action = '{}' AND created_at >= '{}'",
|
||
action.replace("'", "''"), start_time
|
||
);
|
||
|
||
// 正确示例
|
||
let sql = "SELECT * FROM operation_logs WHERE action = $1 AND created_at >= $2";
|
||
sqlx::query_as(sql)
|
||
.bind(&action)
|
||
.bind(&start_time)
|
||
```
|
||
|
||
**涉及文件:**
|
||
- `src/routes/operation_logs.rs`
|
||
- `src/routes/charge_records.rs`
|
||
- `src/routes/energy_stats.rs`
|
||
- `src/routes/downloads.rs`
|
||
|
||
### 2. 密码哈希(🔴 高优先级)
|
||
|
||
**问题位置:** `src/routes/auth.rs:51`
|
||
|
||
**修复方案:**
|
||
集成 `argon2` crate,密码存储和验证使用哈希。
|
||
|
||
```rust
|
||
// Cargo.toml 添加
|
||
argon2 = "0.5"
|
||
|
||
// 密码哈希(创建/重置用户时)
|
||
use argon2::{
|
||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, SaltString},
|
||
Argon2,
|
||
};
|
||
|
||
fn hash_password(password: &str) -> Result<String> {
|
||
let salt = SaltString::generate(&mut OsRng);
|
||
let argon2 = Argon2::default();
|
||
let hash = argon2.hash_password(password.as_bytes(), &salt)?;
|
||
Ok(hash.to_string())
|
||
}
|
||
|
||
// 密码验证(登录时)
|
||
fn verify_password(password: &str, hash: &str) -> Result<bool> {
|
||
let parsed_hash = PasswordHash::new(hash)?;
|
||
let argon2 = Argon2::default();
|
||
Ok(argon2.verify_password(password.as_bytes(), &parsed_hash).is_ok())
|
||
}
|
||
```
|
||
|
||
**涉及文件:**
|
||
- `src/routes/auth.rs` — 登录验证改用 `verify_password`
|
||
- `src/routes/users.rs` — 创建/重置密码改用 `hash_password`
|
||
- `src/db/migrate.rs` — users表password字段长度改为255(argon2哈希较长)
|
||
|
||
### 3. 组织级数据隔离(🔴 高优先级)
|
||
|
||
**问题位置:**
|
||
- `src/routes/organizations.rs` 全部路由
|
||
- `src/routes/charge_records.rs`
|
||
- `src/routes/device_logs.rs`
|
||
- `src/routes/energy_stats.rs`
|
||
|
||
**修复方案:**
|
||
在 `CurrentUser` 中携带 `organization_id`,查询时自动过滤。
|
||
|
||
```rust
|
||
// middleware/auth.rs 修改
|
||
pub struct CurrentUser {
|
||
pub user_id: i64,
|
||
pub role_level: i32, // 0普通 1企业管理员 2总管理员
|
||
pub organization_id: Option<i64>, // 新增
|
||
pub permissions: HashSet<String>,
|
||
}
|
||
|
||
// 查询时根据角色自动过滤
|
||
pub fn apply_org_filter(query: &str, user: &CurrentUser) -> String {
|
||
if user.role_level >= 2 {
|
||
// 总管理员看全部
|
||
query.to_string()
|
||
} else if let Some(org_id) = user.organization_id {
|
||
// 企业管理员只看本组织
|
||
format!("{} WHERE organization_id = {}", query, org_id)
|
||
} else {
|
||
format!("{} WHERE 1=0", query) // 无组织用户看不了
|
||
}
|
||
}
|
||
```
|
||
|
||
**涉及文件:**
|
||
- `src/middleware/auth.rs` — CurrentUser增加organization_id
|
||
- `src/routes/organizations.rs` — 所有查询加组织过滤
|
||
- `src/routes/charge_records.rs` — 加组织过滤
|
||
- `src/routes/device_logs.rs` — 加组织过滤
|
||
- `src/routes/energy_stats.rs` — 加组织过滤
|
||
|
||
### 4. 补充权限校验(🟡 中优先级)
|
||
|
||
**问题位置:**
|
||
- `src/routes/charge_records.rs:158`
|
||
- `src/routes/device_logs.rs:62`
|
||
- `src/routes/energy_stats.rs:81-283`
|
||
- `src/routes/downloads.rs:87`
|
||
|
||
**修复方案:**
|
||
为每个路由添加对应的 `check_permission` 调用。
|
||
|
||
```rust
|
||
// 示例
|
||
#[get("/api/charge-records")]
|
||
async fn list_charge_records(
|
||
user: CurrentUser,
|
||
pool: State<MySqlPool>,
|
||
query: Query<ChargeRecordQuery>,
|
||
) -> Result<Json<Vec<ChargeRecord>>> {
|
||
auth::check_permission(&user, "charge_record:view")?; // 新增
|
||
// ... 原有逻辑
|
||
}
|
||
```
|
||
|
||
**权限码对应:**
|
||
- 充电记录 → `charge_record:view`
|
||
- 设备日志 → `device_log:view`
|
||
- 能耗统计 → `energy:view`
|
||
- 下载中心 → `charge_record:export` 或 `energy:export`
|
||
|
||
## 质量约束
|
||
|
||
1. 完成代码后执行 `cargo check` + `cargo clippy`,零报错零警告
|
||
2. 分层拆分,单函数≤80行,命名语义化,完整注释
|
||
3. 所有外部IO/网络请求异常捕获,禁止裸panic
|
||
4. 分支逻辑全覆盖,不遗漏兜底分支
|
||
5. 常量抽离,不使用废弃API
|
||
6. Rust内存安全,合理管理所有权,禁用unsafe无合理理由
|
||
7. 修复后重新运行审查清单中的安全项目,确保全部通过
|