商業軟體必須解決「誰能用、能用多久、能用什麼功能」的授權問題。本文示範在 Delphi 3/5/7 環境下,以加密 Paradox 資料表 (Users.db) 為核心,建立含使用者帳號、密碼雜湊、角色分組 (系統管理員/操作員/一般用戶/瀏覽者)、啟用/停用旗標、登入失敗鎖定 (3 次) 的完整註冊/登入機制,並採用資料模組分離、介面物件封裝、專案來源修改等工程化實踐。
Login\Data\Users.db (Paradox 5.0, 密碼保護)Login\MD.pas (TDataModule + TTable)Login\Login.pas (TForm + TEdit/TBitBtn)Login\Addition.pas (TApplicationUser 封裝登入後資訊)Register.dpr 控制登入成功才 Application.Run| 欄位 | 型別 | 大小 | 鍵 | 說明 |
|---|---|---|---|---|
| Name | Alpha | 16 | PK | 使用者帳號 |
| Password | Alpha | 16 | PK | 登入密碼 (明文示範,生產環境必須存雜湊) |
| FullName | Alpha | 32 | 顯示名稱 | |
| Group | Integer | 角色:0=超管, 1=操作員, 2=一般, 3=瀏覽 | ||
| Enabled | Logical | 帳號啟用狀態 |
預設值:Group=3, Enabled=True。非空限制:Name, Group, Enabled。
procedure TLoginDialogForm.LoginBitBtnClick(Sender: TObject);
begin
ModalResult := mrNone;
try
Session.AddPassword('UserPassword'); // 解密資料表
LogDataModule.UsersTable.Open;
// 1. 驗證帳號/密碼 (複合鍵查找)
if not LogDataModule.UsersTable.FindKey([LoginNameEdit.Text, PasswordEdit.Text]) then
begin
Dec(CountDown);
if CountDown = 0 then ModalResult := mrCancel
else begin
MessageBeep($FFFF);
Application.MessageBox('請您重試一次!', '無效註冊資訊', MB_ICONSTOP + MB_OK);
LoginNameEdit.SetFocus;
end;
Exit;
end;
// 2. 檢查啟用狀態
if not LogDataModule.UsersTable.FieldByName('Enabled').AsBoolean then
begin
Application.MessageBox('抱歉,您不能進入系統!', '使用權限終止', MB_ICONEXCLAMATION + MB_OK);
ModalResult := mrCancel; Exit;
end;
// 3. 取得使用者資訊填入全域物件
with LogDataModule do
begin
LoginUser.UserName := UsersTable.FieldByName('Name').AsString;
LoginUser.UserFullName := UsersTable.FieldByName('FullName').AsString;
LoginUser.UserGroup := UsersTable.FieldByName('Group').AsInteger;
end;
ModalResult := mrOK;
finally
LogDataModule.UsersTable.Close;
Session.RemovePassword('UserPassword'); // 立即清除記憶體密碼
end;
end;
begin
Application.Initialize;
Application.CreateForm(TLoginDialogForm, LoginDialogForm);
if LoginDialogForm.ShowModal = mrOK then
begin
LoginDialogForm.Free; // 釋放登入視窗資源
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end;
end.
procedure TMainForm.FormActivate(Sender: TObject);
begin
Caption := IfThen(Time < StrToTime('12:00:00'), '上午好,您已成功登錄!', '下午好,您已成功登錄!');
NameEdit.Text := LoginUser.UserName;
FullNameEdit.Text := LoginUser.UserFullName;
GroupEdit.Text := IntToStr(LoginUser.UserGroup);
DisplayDateEdit.Text := DateToStr(Date);
DisplayTimeEdit.Text := TimeToStr(Time);
end;
try...finally 確保 Session.RemovePassword 必執行,防止記憶體掃描竊取。FindKey 直接定位,不遍歷全表。CountDown 計數器,歸零設 ModalResult=mrCancel 關閉登入視窗。LastLogin, LoginCount, ExpireDate 欄位實作授權期限。本方案雖基於經典 Paradox + BDE 架構,但其核心思想 — — **資料加密、最小權限預設、登入防暴力、角色基礎存取控制 (RBAC)、關鍵資源即用即釋** — — 完全適用於現代 Delphi (FireDAC + SQLite/PostgreSQL) 甚至跨語言 (C#/Java) 的授權系統設計。工程化分層 (資料模組、介面物件、專案入口控制) 更是中大型專案可維護的關鍵。