Files
hms/crates/erp-core/src/sanitize.rs
iven 841766b168 fix(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
2026-04-19 08:46:28 +08:00

101 lines
2.6 KiB
Rust

/// HTML/Script 内容清理工具。
///
/// 在用户输入进入数据库之前,剥离所有 HTML 标签,防止存储型 XSS。
/// 覆盖场景:用户名、显示名、邮箱、电话等字符串字段。
/// 剥离字符串中的所有 HTML 标签,返回纯文本。
///
/// ```rust
/// use erp_core::sanitize::strip_html_tags;
/// assert_eq!(strip_html_tags("<script>alert(1)</script>"), "alert(1)");
/// assert_eq!(strip_html_tags("<img src=x onerror=alert(1)>"), "");
/// assert_eq!(strip_html_tags("Hello <b>World</b>"), "Hello World");
/// ```
pub fn strip_html_tags(input: &str) -> String {
let mut result = String::with_capacity(input.len());
let mut in_tag = false;
let mut depth = 0usize;
for ch in input.chars() {
match ch {
'<' => {
in_tag = true;
depth += 1;
}
'>' => {
if depth > 0 {
depth -= 1;
}
if depth == 0 {
in_tag = false;
}
}
_ => {
if !in_tag {
result.push(ch);
}
}
}
}
result.trim().to_string()
}
/// 对 Option<String> 类型的字段进行清理。
pub fn sanitize_option(input: Option<String>) -> Option<String> {
input.map(|s| strip_html_tags(&s)).filter(|s| !s.is_empty())
}
/// 对 String 类型的必填字段进行清理。
pub fn sanitize_string(input: &str) -> String {
strip_html_tags(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strips_script_tag() {
assert_eq!(strip_html_tags("<script>alert('xss')</script>"), "alert('xss')");
}
#[test]
fn strips_img_onerror() {
assert_eq!(strip_html_tags("<img src=x onerror=alert(1)>"), "");
}
#[test]
fn strips_bold_tags() {
assert_eq!(strip_html_tags("Hello <b>World</b>"), "Hello World");
}
#[test]
fn no_tags_passthrough() {
assert_eq!(strip_html_tags("Normal text"), "Normal text");
}
#[test]
fn nested_tags() {
assert_eq!(strip_html_tags("<div><p>text</p></div>"), "text");
}
#[test]
fn sanitize_option_some() {
assert_eq!(
sanitize_option(Some("<script>evil</script>".to_string())),
Some("evil".to_string())
);
}
#[test]
fn sanitize_option_none() {
assert_eq!(sanitize_option(None), None);
}
#[test]
fn sanitize_option_becomes_empty() {
assert_eq!(sanitize_option(Some("<img>".to_string())), None);
}
}