首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言用戶註冊登錄數據持久化:文件存儲與加密方案

     編輯:程式設計綜合問答

方案選型對比

方案優點缺點適用場景
文本文件 (明文/簡單加密)零依賴、易調試、移植性強併發寫入難、查詢慢、安全性弱單用戶桌面工具、教學演示、嵌入式設備
SQLite (嵌入式數據庫)SQL 查詢、事務、併發、單文件需鏈接庫、稍大本地應用、移動端、中小型項目
MySQL/PostgreSQL 客戶端庫企業級特性、網絡透明需獨立服務進程、部署複雜C/S 架構、多用戶並發、生產系統

方案 A:文本文件 + 簡單加密 (教學級)

數據結構

typedef struct {
    char username[32];
    char password_hash[65]; // SHA-256 hex 64 字符 + \0
    char salt[17];          // 16 字節隨機鹽 + \0
} UserRecord;

核心函數

// 註冊
bool registerUser(const char *username, const char *password) {
    // 1. 檢查用戶名是否存在
    // 2. 生成隨機鹽
    // 3. 計算 hash = SHA256(salt + password)
    // 4. 追加寫入文件
    FILE *fp = fopen("users.dat", "ab");
    if (!fp) return false;
    UserRecord rec;
    strncpy(rec.username, username, 31);
    // ... 填充 salt, password_hash
    fwrite(&rec, sizeof(UserRecord), 1, fp);
    fclose(fp);
    return true;
}

// 登錄驗證
bool loginUser(const char *username, const char *password) {
    FILE *fp = fopen("users.dat", "rb");
    if (!fp) return false;
    UserRecord rec;
    while (fread(&rec, sizeof(UserRecord), 1, fp) == 1) {
        if (strcmp(rec.username, username) == 0) {
            // 計算 hash = SHA256(rec.salt + password)
            // 比較 hash == rec.password_hash
            fclose(fp);
            return true; // 簡化
        }
    }
    fclose(fp);
    return false;
}

加密關鍵點

  • 不可存明文密碼:必須存鹽值哈希。
  • 使用成熟哈希:SHA-256 (需外部庫如 OpenSSL/mbedTLS) 或 PBKDF2/bcrypt/argon2 (更安全)。
  • 防時序攻擊:比較哈希用恒定時間比較函數。

方案 B:SQLite 3 嵌入式數據庫 (推薦生產級)

優勢

  • 標準 SQL,支持索引、事務、併發 (WAL 模式)。
  • 單文件 users.db,無需服務進程。
  • C API 成熟穩定,sqlite3.h + sqlite3.c 直接編入項目。

關鍵代碼片段

sqlite3 *db;
sqlite3_open("users.db", &db);
sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS users ("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "username TEXT UNIQUE NOT NULL,"
    "password_hash TEXT NOT NULL,"
    "salt TEXT NOT NULL"
")", 0, 0, 0);

// 註冊 (參數化查詢防注入)
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "INSERT INTO users (username, password_hash, salt) VALUES (?, ?, ?)", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, hash, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, salt, -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);

// 登錄
sqlite3_prepare_v2(db, "SELECT password_hash, salt FROM users WHERE username = ?", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_TRANSIENT);
if (sqlite3_step(stmt) == SQLITE_ROW) {
    const char *db_hash = (const char*)sqlite3_column_text(stmt, 0);
    const char *db_salt = (const char*)sqlite3_column_text(stmt, 1);
    // 驗證...
}
sqlite3_finalize(stmt);
sqlite3_close(db);

安全最佳實踐清單

  1. 密碼最小長度 8 位,強制大小寫數字特殊字符混合。
  2. 使用 **Argon2id** (推薦) 或 **bcrypt** / **PBKDF2-HMAC-SHA256** (迭代 ≥ 100,000)。
  3. 登錄失敗限制嘗試次數 + 鎖定時間 (防暴力破解)。
  4. 敏感操作記錄審計日志 (用戶、時間、IP、操作)。
  5. 文件/數據庫權限設置為僅擁有者讀寫 (chmod 600)。

總結建議

  • **教學/玩具項目**:文本文件 + SHA-256 即可,重點理解「鹽值哈希」概念。
  • **實際產品/課程設計**:**直接用 SQLite**,代碼量差異不大,但健壯性、可擴展性、面試加分項質變。
  • **切勿自行設計加密算法**,務必調用成熟密碼學庫 (OpenSSL, libsodium, mbedTLS)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved