安全错误处理
原理
企业级错误处理的三大安全维度:
错误信息泄漏:外部错误消息不得暴露内部实现细节(栈追踪、文件路径、数据库结构、内部 IP)。区分 internal error(日志)和 public error(客户端返回)。
错误处理完整性:所有 IO 操作、网络请求、解析、转换必须处理 Result。库代码不应 unwrap() 或 expect()(除在已证明的不变量处)。应用层可 panic 但应有全局 set_hook。
错误类型体系:使用 thiserror 构建结构化错误类型,使用 anyhow 简化应用层错误传播。库层提供枚举错误类型供调用者匹配,应用层可使用 Box<dyn Error> 或 anyhow::Error。
安全失败的默认策略:权限检查失败 → 拒绝访问(而非默许)。加密失败 → 中止(而非降级明文)。验证失败 → 回滚事务。
语法
// thiserror — 库层结构化错误
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ServiceError {
#[error("authentication failed: {0}")]
Auth(String),
#[error("database error: {0}")]
Database(#[from] sqlx::Error),
#[error("invalid input: {0}")]
Validation(String),
}
// anyhow — 应用层简化
use anyhow::{Context, Result};
fn app_main() -> Result<()> {
let config = read_config("config.toml")
.context("failed to read config")?;
Ok(())
}
// 全局 panic hook
use std::panic;
panic::set_hook(Box::new(|info| {
tracing::error!("panic: {}", info);
std::process::abort();
}));实践
AI 自检
thiserror和anyhow的区别?各自适用什么场景?- CWE-209(错误信息泄漏)在 Rust 中如何防范?举一个实际的例子。