首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言模擬登入系統:三次密碼嘗試限制完整實作

     編輯:關於C語言

C語言模擬登入系統:三次密碼嘗試限制完整實作

模擬使用者登入、限制嘗試次數是 C 語言基礎 I/O、字串比較、迴圈控制的綜合練習。本文提供標準實作、安全性強化版(隱藏輸入、緩衝區保護)、以及擴展方向(帳號鎖定、日誌記錄、多使用者支援)。

基礎版實作

#include <stdio.h>
#include <string.h>

int main() {
    const char *password = "123456";  // 預設密碼
    char input[20];
    int attempts = 0;
    const int MAX_ATTEMPTS = 3;

    for (attempts = 0; attempts < MAX_ATTEMPTS; attempts++) {
        printf("請輸入密碼: ");
        if (scanf("%19s", input) != 1) {  // 限制長度防溢位
            printf("輸入錯誤\n");
            continue;
        }

        if (strcmp(password, input) == 0) {
            printf("登入成功!\n");
            break;
        } else {
            printf("密碼錯誤,剩餘嘗試 %d 次\n", MAX_ATTEMPTS - attempts - 1);
        }
    }

    if (attempts == MAX_ATTEMPTS) {
        printf("錯誤次數過多,帳號暫時鎖定\n");
    }

    return 0;
}

安全性強化版:隱藏輸入與緩衝區保護

#include <stdio.h>
#include <string.h>
#include <termios.h>  // Linux/Unix 隱藏輸入
#include <unistd.h>   // STDIN_FILENO

// 關閉回顯
void disableEcho() {
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    tty.c_lflag &= ~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &tty);
}

// 開啟回顯
void enableEcho() {
    struct termios tty;
    tcgetattr(STDIN_FILENO, &tty);
    tty.c_lflag |= ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &tty);
}

// 安全讀取一行(含長度限制、去換行)
bool readLineSafe(char *buf, size_t bufSize) {
    if (fgets(buf, bufSize, stdin) == NULL) return false;
    size_t len = strlen(buf);
    if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
    return true;
}

int main() {
    const char *password = "123456";
    char input[20];
    int attempts = 0;
    const int MAX_ATTEMPTS = 3;

    printf("=== 登入系統 ===\n");
    for (attempts = 0; attempts < MAX_ATTEMPTS; attempts++) {
        printf("密碼: ");
        disableEcho();  // 隱藏輸入
        bool ok = readLineSafe(input, sizeof(input));
        enableEcho();   // 恢復回顯
        printf("\n");

        if (!ok) {
            printf("讀取失敗\n");
            continue;
        }

        if (strcmp(password, input) == 0) {
            printf("✅ 登入成功!歡迎回來。\n");
            return 0;
        } else {
            int remain = MAX_ATTEMPTS - attempts - 1;
            if (remain > 0)
                printf("❌ 密碼錯誤,還有 %d 次機會。\n", remain);
        }
    }

    printf("🔒 錯誤次數達上限,帳號已鎖定。請稍後再試或聯繫管理員。\n");
    return 1;
}

Windows 版隱藏輸入

#include <windows.h>
#include <conio.h>  // _getch

void readPasswordWin(char *buf, int maxLen) {
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);
    SetConsoleMode(hStdin, mode & ~ENABLE_ECHO_INPUT);  // 關閉回顯

    int i = 0;
    while (i < maxLen - 1) {
        int ch = _getch();
        if (ch == '\r' || ch == '\n') break;
        if (ch == 8 || ch == 127) {  // Backspace
            if (i > 0) {
                i--;
                printf("\b \b");  // 視覺回退
            }
        } else {
            buf[i++] = ch;
            putchar('*');  // 顯示星號
        }
    }
    buf[i] = '\0';

    SetConsoleMode(hStdin, mode);  // 恢復模式
    printf("\n");
}

進階擴展架構

// 使用者結構
typedef struct {
    char username[32];
    char passwordHash[64];  // 存儲雜湊而非明文
    int failedAttempts;
    time_t lockUntil;       // 鎖定解除時間
    bool isLocked;
} User;

// 驗證流程
bool authenticate(User *user, const char *inputPass) {
    if (user->isLocked && time(NULL) < user->lockUntil) {
        printf("帳號鎖定中,%ld 秒後解鎖\n", user->lockUntil - time(NULL));
        return false;
    }
    if (verifyHash(inputPass, user->passwordHash)) {  // bcrypt/argon2 驗證
        user->failedAttempts = 0;
        user->isLocked = false;
        return true;
    } else {
        user->failedAttempts++;
        if (user->failedAttempts >= 5) {
            user->isLocked = true;
            user->lockUntil = time(NULL) + 300;  // 鎖定 5 分鐘
        }
        return false;
    }
}

安全最佳實踐清單

  • ✅ 絕不儲存明文密碼:使用 bcrypt、Argon2、PBKDF2 等慢速雜湊演算法。
  • ✅ 限制輸入長度:scanf("%19s")、fgets(buf, sizeof(buf)) 防止緩衝區溢位。
  • ✅ 隱藏密碼輸入:關閉終端機回顯或顯示星號。
  • ✅ 失敗延遲:錯誤後 sleep(1) 增加暴力破解成本。
  • ✅ 帳號鎖定機制:達閾值暫時鎖定,記錄解鎖時間。
  • ✅ 審計日誌:記錄登入嘗試(時間、IP、成功/失敗),不記錄密碼。
  • ✅ 常數時間比較:驗證雜湊時使用 timingsafe_bcmp 防止時序攻擊。

從簡單的三次嘗試限制出發,逐步建立完整的認證安全體系,是每位後端開發者必經的成長路徑。建議實作上述強化版,並嘗試整合 SQLite 儲存使用者資料、使用 OpenSSL 進行密碼雜湊,打造可用於實際專案的登入模組。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved