┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 前端UI层 │ │ Rust核心层 │ │ 系统层 │
│ (Vue3+TS) │◄──►│ (Tauri后端) │◄──►│ (OS API) │
│ │ │ │ │ │
│ ✅ 无敏感逻辑 │ │ ✅ 核心业务逻辑 │ │ ✅ 受限系统访问 │
│ ✅ UI展示 │ │ ✅ 数据加密 │ │ ✅ 沙箱环境 │
│ ✅ 用户交互 │ │ ✅ 安全验证 │ │ ✅ 权限控制 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
// Rust编译器保证内存安全
fn safe_memory_handling(data: &str) -> Result<String, Box<dyn std::error::Error>> {
// 不可能出现缓冲区溢出、空指针解引用等内存安全问题
Ok(data.to_string())
}
// 编译时检查资源所有权,防止数据竞争
fn secure_data_handling(mut data: Vec<u8>) -> Vec<u8> {
// data的所有权在函数内部,不会发生并发访问冲突
data
}
// 强类型系统防止类型混淆攻击
#[derive(Debug, Serialize, Deserialize)]
struct SecureAccount {
username: String,
encrypted_password: Vec<u8>,
session_token: Option<String>,
}
use aes_gcm::{Aes256Gcm, Key, Nonce};
use aes_gcm::aead::{Aead, KeyInit};
fn encrypt_sensitive_data(data: &[u8], key: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(b"unique nonce"); // 实际使用随机nonce
let ciphertext = cipher.encrypt(nonce, data)
.map_err(|e| format!("Encryption failed: {}", e))?;
Ok(ciphertext)
}
use pbkdf2::pbkdf2_hmac;
use sha2::Sha256;
fn derive_key(password: &str, salt: &[u8]) -> [u8; 32] {
let mut key = [0u8; 32];
pbkdf2_hmac::<Sha256>(password.as_bytes(), salt, 100_000, &mut key);
key
}
use zeroize::Zeroize;
struct SensitiveData {
api_key: String,
session_token: Vec<u8>,
}
impl Drop for SensitiveData {
fn drop(&mut self) {
self.api_key.zeroize();
self.session_token.zeroize();
}
}
use ring::rand::{SecureRandom, SystemRandom};
fn generate_secure_random_bytes(length: usize) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let rng = SystemRandom::new();
let mut bytes = vec![0u8; length];
rng.fill(&mut bytes)
.map_err(|_| "Failed to generate random bytes".into())?;
Ok(bytes)
}
use reqwest::Client;
async fn secure_http_request(url: &str) -> Result<String, Box<dyn std::error::Error>> {
let client = Client::builder()
.https_only(true) // 强制HTTPS
.timeout(std::time::Duration::from_secs(30))
.build()?;
let response = client.get(url).send().await?;
let cert = response.extensions().get::<reqwest::tls::Certificate>();
// 验证证书指纹
if let Some(cert) = cert {
verify_certificate_fingerprint(cert)?;
}
Ok(response.text().await?)
}
use hmac::{Hmac, Mac};
use sha256::Sha256;
fn sign_request(method: &str, url: &str, body: &str, secret: &str) -> String {
let message = format!("{}{}{}", method, url, body);
let mut mac = Hmac::<Sha256>::new_from_slice(secret.as_bytes())
.expect("HMAC can take key of any size");
mac.update(message.as_bytes());
let result = mac.finalize();
let code_bytes = result.into_bytes();
hex::encode(code_bytes)
}
// 每个会话使用独立的浏览器上下文
pub async fn create_isolated_session(&mut self, session_id: &str)
-> Result<(), Box<dyn std::error::Error>> {
let context = self.browser.context_builder()
.user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...")
.viewport(1920, 1080)
.permissions(vec![]) // 禁用不必要的权限
.build()
.await?;
// 设置安全策略
context.add_init_script(r#"
// 禁用危险的JavaScript API
delete window.chrome;
delete window.opera;
delete navigator.webdriver;
// 限制网络请求
const originalFetch = window.fetch;
window.fetch = function(url, options) {
// 只允许Steam相关的域名
if (!url.includes('steampowered.com') && !url.includes('steamcommunity.com')) {
throw new Error('Blocked request to unauthorized domain');
}
return originalFetch(url, options);
};
"#).await?;
self.contexts.insert(session_id.to_string(), context);
Ok(())
}
// 限制浏览器资源使用
let browser = playwright.chromium()
.launcher()
.args(vec![
"--disable-dev-shm-usage".to_string(),
"--disable-accelerated-2d-canvas".to_string(),
"--max_old_space_size=4096".to_string(), // 限制内存
"--disable-background-timer-throttling".to_string(),
"--disable-renderer-backgrounding".to_string(),
])
.launch()
.await?;
// 在页面上下文中注入脚本来伪装环境
context.add_init_script(`
// 修改navigator属性
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
});
// 添加插件信息
Object.defineProperty(navigator, 'plugins', {
get: () => [
{ name: 'Chrome PDF Plugin', description: 'Portable Document Format', filename: 'internal-pdf-viewer' },
{ name: 'Chrome PDF Viewer', description: '', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai' },
{ name: 'Native Client', description: '', filename: 'internal-nacl-plugin' }
],
});
// 修改权限
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
`).await?;
// 随机延迟和鼠标移动来模拟人类行为
async fn human_like_interaction(page: &Page, selector: &str) -> Result<(), Box<dyn std::error::Error>> {
use rand::Rng;
let mut rng = rand::thread_rng();
// 随机延迟
let delay = rng.gen_range(500..2000);
tokio::time::sleep(tokio::time::Duration::from_millis(delay)).await;
// 鼠标移动到元素
let element = page.locator(selector).first().await?;
let bounding_box = element.bounding_box().await?;
let center_x = bounding_box.x + bounding_box.width / 2.0;
let center_y = bounding_box.y + bounding_box.height / 2.0;
// 模拟人类鼠标移动(贝塞尔曲线)
page.mouse().move_to(center_x, center_y, None).await?;
// 随机点击延迟
let click_delay = rng.gen_range(100..500);
tokio::time::sleep(tokio::time::Duration::from_millis(click_delay)).await;
element.click().await?;
Ok(())
}
#[cfg(target_os = "windows")]
fn detect_debugger() -> bool {
use winapi::um::debugapi::IsDebuggerPresent;
unsafe { IsDebuggerPresent() != 0 }
}
#[cfg(target_os = "linux")]
fn detect_debugger() -> bool {
use std::fs;
if let Ok(content) = fs::read_to_string("/proc/self/status") {
content.contains("TracerPid:\t") &&
!content.contains("TracerPid:\t0")
} else {
false
}
}
fn anti_debug_check() {
if detect_debugger() {
eprintln!("Debugger detected! Exiting for security.");
std::process::exit(1);
}
}
fn detect_timing_attack() -> bool {
use std::time::Instant;
let start = Instant::now();
// 执行一些计算
let mut sum = 0u64;
for i in 0..1000000 {
sum = sum.wrapping_add(i);
}
let elapsed = start.elapsed();
// 如果执行时间异常(可能是调试器干扰),则认为是调试环境
elapsed.as_millis() > 100 // 阈值可调整
}
use ring::digest::{Context, SHA256};
fn calculate_file_hash(path: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut context = Context::new(&SHA256);
let mut file = std::fs::File::open(path)?;
let mut buffer = [0; 1024];
loop {
let bytes_read = file.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
context.update(&buffer[..bytes_read]);
}
let digest = context.finish();
Ok(hex::encode(digest.as_ref()))
}
fn verify_integrity(expected_hash: &str) -> bool {
match calculate_file_hash(std::env::current_exe().unwrap().to_str().unwrap()) {
Ok(actual_hash) => actual_hash == expected_hash,
Err(_) => false,
}
}
struct SecurityMonitor {
suspicious_activities: Vec<String>,
max_attempts: u32,
lockout_duration: std::time::Duration,
}
impl SecurityMonitor {
fn new() -> Self {
SecurityMonitor {
suspicious_activities: Vec::new(),
max_attempts: 5,
lockout_duration: std::time::Duration::from_secs(300), // 5分钟
}
}
fn record_activity(&mut self, activity: &str, severity: Severity) {
let timestamp = chrono::Utc::now();
let log_entry = format!("[{}] {}: {}", timestamp, severity, activity);
self.suspicious_activities.push(log_entry);
// 达到阈值时触发安全响应
if self.suspicious_activities.len() >= self.max_attempts as usize {
self.trigger_security_response();
}
}
fn trigger_security_response(&self) {
// 安全响应措施
eprintln!("Security alert: Multiple suspicious activities detected!");
// 清除敏感数据
// 终止当前会话
// 通知服务器
// 记录安全事件
}
}
use log::{Level, LevelFilter, Record};
struct SecureLogger;
impl log::Log for SecureLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
let timestamp = chrono::Utc::now();
let level = record.level();
let message = record.args();
// 过滤敏感信息
let safe_message = sanitize_log_message(&format!("{}", message));
// 加密日志存储
let encrypted_log = encrypt_log_entry(&safe_message);
// 写入安全日志文件
write_secure_log(&encrypted_log);
}
}
fn flush(&self) {}
}
fn sanitize_log_message(message: &str) -> String {
// 移除API密钥、密码等敏感信息
message
.replace(r"(?i)(api[_-]?key|password|token|secret)[\s]*[=:][\s]*[^\s]+", "[REDACTED]")
.replace(r"\b\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}\b", "[CARD_NUMBER_REDACTED]")
}
# Cargo.toml
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"
strip = true
# 检查依赖的安全漏洞
cargo audit
# 检查过时的依赖
cargo outdated
# 生成依赖图
cargo tree
// tauri.conf.json
{
"tauri": {
"allowlist": {
"all": false,
"fs": {
"all": false,
"readFile": true,
"writeFile": true,
"scope": ["$APPDATA/*"]
},
"http": {
"all": false,
"request": true,
"scope": ["https://api.steampowered.com/*", "https://steamcommunity.com/*"]
}
}
}
}
通过多层安全架构、强类型语言、加密存储、网络安全保护、浏览器隔离、运行时监控等全方位安全措施,我们确保了系统的安全性:
这种深度防御策略确保了即使部分防护被突破,其他层面的防护仍能发挥作用。