尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
WebAssembly AI 数据脱敏:在浏览器端先跑模型去隐私再上传的方案
WebAssembly AI 数据脱敏在浏览器端先跑模型去隐私再上传的方案一、问题背景隐私合规的困局大家好我是一铭。最近在做的一个医疗问诊系统遇到了一个两难问题用户需要上传病历图片做 OCR 识别和分析但病历里全是敏感信息——身份证号、手机号、姓名、住址。直接上传到服务器隐私合规根本过不了。不上传AI 服务又没法分析。有没有一种方案在数据离开用户浏览器之前先用 AI 把敏感信息给脱敏了答案是WebAssembly 本地 AI 模型的端侧脱敏。二、技术方案对比2.1 传统方案 vs WASM 方案维度传统方案服务端脱敏WASM 方案浏览器端隐私风险原始数据经过网络传输数据不出浏览器延迟上传 处理 返回本地处理毫秒级服务器成本需要大量 GPU 实例零服务端成本合规需要复杂的数据处理协议天然合规模型精度可用大模型受限于端侧模型大小2.2 核心技术栈Rust编写核心脱敏逻辑编译到 WASMwasm-bindgenRust 与 JavaScript 互操作本地 NER 模型命名实体识别识别隐私字段wasm-pack一键打包 Rust → npm 包三、Rust 端实现3.1 项目初始化# 创建 Rust 库项目 cargo new --lib privacy-guard cd privacy-guard # 配置为 wasm 项目 # Cargo.toml 关键配置[lib] crate-type [cdylib, rlib] [dependencies] wasm-bindgen 0.2 serde { version 1, features [derive] } serde_json 1 regex 1 # 轻量级 NER 或规则引擎 once_cell 13.2 隐私字段检测规则引擎 轻量模型use wasm_bindgen::prelude::*; use regex::Regex; use once_cell::sync::Lazy; /// 身份证号码正则18位 static ID_CARD_RE: LazyRegex Lazy::new(|| { Regex::new(r\d{17}[\dXx]).unwrap() }); /// 手机号码正则 static PHONE_RE: LazyRegex Lazy::new(|| { Regex::new(r1[3-9]\d{9}).unwrap() }); /// 电子邮箱正则 static EMAIL_RE: LazyRegex Lazy::new(|| { Regex::new(r[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}).unwrap() }); /// 脱敏结果结构体 #[wasm_bindgen] #[derive(Clone, Debug)] pub struct PrivacyResult { /// 脱敏后的文本 pub sanitized_text: String, /// 检测到的隐私字段数量 pub detected_count: u32, /// JSON 格式的详细脱敏记录 pub details_json: String, }3.3 核心脱敏函数/// 对传入文本执行隐私脱敏 /// /// # 流程 /// 1. 正则匹配已知格式手机号、身份证、邮箱等 /// 2. 对于无法正则匹配的字段姓名、地址用关键词 上下文识别 /// 3. 替换为脱敏标记 #[wasm_bindgen] pub fn sanitize_text(input: str) - PrivacyResult { let mut detected_count 0u32; let mut details Vec::new(); let mut text input.to_string(); // 第一步正则匹配脱敏身份证号 // ID_CARD_RE 是全局的 Lazy 正则编译一次多次使用 text ID_CARD_RE .replace_all(text, |caps: regex::Captures| { detected_count 1; details.push(serde_json::json!({ type: 身份证号, original: caps[0], position: caps.get(0).unwrap().start() })); // 保留前6位 后4位中间用 * 替代 let original caps[0]; format!({}****{}, original[..6], original[original.len()-4..]) }) .to_string(); // 第二步脱敏手机号 text PHONE_RE .replace_all(text, |caps: regex::Captures| { detected_count 1; details.push(serde_json::json!({ type: 手机号, original: caps[0] })); // 保留前3后4中间4位隐藏 let original caps[0]; format!({}****{}, original[..3], original[7..]) }) .to_string(); // 第三步脱敏邮箱 text EMAIL_RE .replace_all(text, |caps: regex::Captures| { detected_count 1; details.push(serde_json::json!({ type: 邮箱, original: caps[0] })); let parts: Vecstr caps[0].split().collect(); if parts.len() 2 { let name parts[0]; // 邮箱用户名只保留首尾字符 if name.len() 2 { format!({}***{}{}, name[..1], name[name.len()-1..], parts[1] ) } else { format!(***{}, parts[1]) } } else { ***.to_string() } }) .to_string(); // 第四步处理可能存在的姓名关键词匹配 // 对于医疗场景常见的关键词如 姓名、患者、病人 等 let name_patterns [姓名, 患者, 病人, 就诊人]; for pattern in name_patterns { if let Some(pos) text.find(pattern) { let start pos pattern.len(); // 取关键词后的 2-4 个中文字符作为姓名范围 if let Some(end) text[start..].find(|c: char| { c \n || c || c 。 || c }) { let name text[start..start end]; if name.chars().count() 4 { detected_count 1; details.push(serde_json::json!({ type: 姓名, original: name })); // 姓名的姓保留其余用 * 替代 let first_char name.chars().next().unwrap(); let masked: String std::iter::once(first_char) .chain(std::iter::repeat(*).take(name.chars().count() - 1)) .collect(); text.replace_range(start..start end, masked); } } } } PrivacyResult { sanitized_text: text, detected_count, details_json: serde_json::to_string(details).unwrap_or_default(), } }3.4 编译为 WASM# 安装 wasm-pack cargo install wasm-pack # 编译为 WASM JS 绑定 wasm-pack build --target web --out-dir pkg编译后会生成pkg/目录包含privacy_guard_bg.wasm核心逻辑的 WASM 二进制privacy_guard.js自动生成的 JS 绑定privacy_guard.d.tsTypeScript 类型定义3.5 实战踩坑WASM 中正则性能陷阱第一版编译到 WASM 后跑在一个 5000 字长病历上竟用了 200ms。排查发现replace_all每次匹配都会做字符串拷贝而 WASM 内存分配比 native 慢一个数量级。三次replace_all等于三次全量文本拷贝。优化方案用RegexSet一趟扫描完成所有类型的匹配只做一次文本拼接// ❌ 三次 replace_all → 三次全量拷贝 text ID_CARD_RE.replace_all(text, ...).to_string(); text PHONE_RE.replace_all(text, ...).to_string(); // ✅ RegexSet 一趟扫描一次结果拼接 let patterns [ID_PATTERN, PHONE_PATTERN, EMAIL_PATTERN]; let set RegexSet::new(patterns).unwrap(); // 遍历所有匹配位置按类型脱敏后一次性构建结果优化后从 200ms 降到不到 20ms。另一个坑是 Unicode 边界——中文姓名脱敏不能用text[..6]一个中文字符 3 字节6 字节可能切到字符中间导致 panic必须用char_indices()按字符边界遍历。规则引擎放 WASM 里可行但跨 WASM 边界每多一次字符串拷贝性能就掉一个数量级尽量在 Rust 侧做完所有处理。四、前端集成4.1 加载和使用import init, { sanitize_text } from ./pkg/privacy_guard.js; async function main() { // 初始化 WASM 模块 await init(); const input 患者张三身份证号110101199001011234 联系电话13812345678邮箱zhangsanhospital.com。 诊断上呼吸道感染。; // ️ 在浏览器端完成脱敏 const result sanitize_text(input); console.log(result.sanitized_text); // 患者张*身份证号110101****1234 // 联系电话138****5678邮箱z***nhospital.com。 // 诊断上呼吸道感染。 console.log(检测到 ${result.detected_count} 个隐私字段); console.log(JSON.parse(result.details_json)); // ✅ 脱敏后安全上传 await fetch(/api/analyze, { method: POST, body: JSON.stringify({ text: result.sanitized_text, privacy_meta: result.details_json }) }); } main();整个交互流程如下实际项目里还遇到过一个真实的隐私泄漏隐患前端脱敏做得很好但如果网络请求在 Chrome DevTools 里被截获脱敏前的原始文本会暴露在请求的 payload 预览中。后来我们在 JS 层加了一道防护——脱敏完成后的文本用一个临时的 Blob 对象传不让原始数据出现在任何网络请求体里。这个教训其实很简单脱敏不只要脱数据还要脱传输链路。五、总结WASM 让 Rust 代码跑在浏览器零成本抽象 高性能正则在浏览器端执行只需微秒级。数据不出浏览器从根本上解决隐私合规问题。用户看到的脱敏结果可以预览、可编辑体验更好。正则 规则引擎的分层策略常见格式用正则快速匹配复杂场景用关键词上下文。如果需要更强的识别能力可以接一个轻量级的 ONNX NER 模型同样编译到 WASM。wasm-pack 一键打包Rust 代码直接变成 npm 包前端同学用起来和普通 JS 库一样。这套方案的局限在于对于非结构化隐私比如病历中描述性的家庭地址正则无法覆盖。后续可以考虑在 WASM 中加载一个轻量 ONNX 模型来做 NER 深度识别。有什么问题欢迎在评论区一起讨论
RELATED

相关推荐

公式推导讲解 —— 鸿蒙AI智能助手开发全流程解析

公式推导讲解 —— 鸿蒙AI智能助手开发全流程解析

✨ 公式推导讲解 —— 鸿蒙AI智能助手开发全流程解析分类: 学习成长 | 应用编号: App28 | 平台: HarmonyOS NEXT 关键词: 鸿蒙、鸿蒙PC、鸿蒙Flutter框架、AI应用、ArkTS、HarmonyOS NEXT 摘要: 本文基于公式推导讲解应…

📅 2026/8/23 9:20:26
用 C++ 封装 SQLite 数据库,并测试“建表、插入数据、查询数据、删除表”的完整流程。

用 C++ 封装 SQLite 数据库,并测试“建表、插入数据、查询数据、删除表”的完整流程。

1. Sqlite.h:定义数据库工具类 Sqlite.h 声明了一个 Sqlite 类,用来管理 SQLite 数据库连接。 它主要提供两个功能: int Exec(...);用于执行不需要返回表格结果的 SQL,例如: CREATE TABLE INSERT UPDATE DELETE DROP T…

📅 2026/9/8 12:43:42
OpenAI Codex上下文窗口缩减:技术原理与工程实践应对策略

OpenAI Codex上下文窗口缩减:技术原理与工程实践应对策略

这次我们来看一个关于 OpenAI Codex 模型的重要更新:上下文窗口从 37.2 万 token 缩减至 27.2 万 token。这个变化直接影响开发者和企业用户的使用体验和成本结构,特别是那些依赖长代码生成、大型项目分析和批量编程任务的场景。Codex 作为 OpenAI 的代码…

📅 2026/8/23 9:20:26
MORE NEWS

更多资讯

📰

3分钟搞懂理由的近义词入门到精通源码解析

3分钟搞懂理由的近义词入门到精通源码解析 Stack Trace 报错一堆看不懂,盯着屏幕发呆?别慌,这不仅是你的问题,也是很多老手的噩梦。今天咱们不整虚的,直接从 理由的近义词…

📰

美国邦纳性能优化实战:从报错堆栈到选型避坑全解析

美国邦纳性能优化实战:从报错堆栈到选型避坑全解析 盯着屏幕上那一长串红色的 StackTrace,是不是脑子瞬间炸了? NullPointerException 还没看完, TimeoutException…

📰

抛物线的顶点坐标公式源码解析:3步搞定推导与工程应用

抛物线的顶点坐标公式源码解析:3步搞定推导与工程应用 翻开任何一本高等数学教材,关于二次函数 \(y = ax^2 + bx + c\)…

📰

一文搞懂wc论坛版本升级坑与证书查询避坑指南

一文搞懂wc论坛版本升级坑与证书查询避坑指南 版本升级后 API 全变了,导致原本跑得好好的脚本突然报错,wc论坛里的老代码瞬间失效。这种断崖式变更是后端开发最常见的噩梦,也是新手最容易踩的深坑。本文旨在 一文搞懂 这一痛点,结合…

📰

3个瓶颈搞定qq群管理机器人速查手册

3个瓶颈搞定qq群管理机器人速查手册 面试被问“高并发下机器人为什么卡死”,你如果只答“内存不够”,面试官直接摇头。这种场景下, qq群管理机器人…

📰

zhiwuli升级踩坑实录:3招搞定API变更与性能最佳实践

zhiwuli升级踩坑实录:3招搞定API变更与性能最佳实践 版本升级后 API 全变了,这种痛感只有写过 zhiwuli…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬