軟件的安全性是個永恆的話題, 一直困擾著人們,程序員們常常因此熬夜。Novell公司的網絡操作系統NetWare 以其完善可靠的安全管理機制著稱,為實現用戶登錄的安全性和防止非法入侵者闖入,系統提供了幾種有效的限制措施和檢測功能。本文討論如何 建立完善的軟件注冊安全機制,有效地管理用戶登錄,為應用軟件提供可靠的保護,並在Delphi3.0下實現。
Delphi作為一個優秀的編程工具,功能極其強大,令開發周期大大縮短,生成的代碼運行速度快,使得Windows 軟件設計成為一種樂趣。基本思路是:建立Paradox格式的用戶帳戶表Users.DB,並加密保護,由管理員維護。預先在此表中登記並有注冊權限的用戶,可持本人有效口令登錄進入系統。
實現步驟如下:
1.在應用軟件主目錄(假設為C:\Register) 下創建兩個子目錄,分別命名為Login和Data。
2.從Delphi的Tools菜單中啟動Database Desktop,並選擇Tools/AliasManager…創建一個新別名。方法是:在Alias Manager對話框中點New,給出新別名UserInfo,並指向C:\Register\Data 目錄,按KeepNew、OK等按鈕保存新別名。
3.利用DatabaseDesktop創建Paradox 5.0 for Windows數據表Users.DB,結構見表1。事實上,對於商業軟件還需要更多的域。
域名 類型 大小 關鍵字 說明
Name A 16 * 用戶名
Password A 16 * 注冊口令
Fullname A 32 用戶全名
Group I 用戶組號
Enabled L 注冊允許
4.設定Name,Group和Enabled 為非空域(RequiredField),Group的最小值為0,最大值為3,默認值為3,Enabled的默認值為True。用戶組0為系統管理員,可進行幾乎任何操作;用戶組1為 軟件操作人員,可進行除用戶帳戶管理以外的操作,包括建立和刪除數據;用戶組2為普通用戶,可使用系統資源,無修改權限,而用戶組3僅可浏覽系 統有限信息。
5.用口令UserPassword 保護Users.DB表,存於Data目錄下。利用DatabaseDesktop向表中輸入若干樣本用戶(見表2),然後關閉DatabaseDesktop。
表2表Users.DB的樣本用戶
Name Pa ord Fullname Group Enabled Supervisor AAAAAA Super User 0 True Director BBBBBB Director User 1 True Guest 3 True User1 CCCCCC General User1 1 False User1 DDDDDD General User1 2 True User2 EEEEEE General User2 3 True
表2顯示,允許同一用戶以不同身 份(用戶組)登錄進入系統,享有不同的權限。如用戶User1,以不同密碼登 記,分屬用戶組1和2。
6.返回DelphiIDE,新建項目Register.dpr 並存入C:\Register目錄,主窗體單元命名為Main.pas。用戶注冊成功後,方能啟動主窗體進入系統。本系統僅顯示用戶信息及登錄的日期和時間以 表示注冊成功(見圖5),並不做其它任何事情,這裡便是讀者應用系統的接口。為此,在主窗體上放入一個TGroupBox組件,TLabel和TEdit組件各五個。 將所有TEdit的Text屬性清空,ReadOnly屬性值設為True,窗體和組件其余屬性按表3設置。
7.創建主窗體的OnActivate事 件處理程序,登錄成功並激活主窗體時執行,顯示用戶信息、登錄日期和時 間。過程如下:
procedureTMainForm.FormActivate(Sender:TObject);
begin
ifTime=StrToTime(12:00:00)then
Caption:=上午好,您已成功登錄!
else
Caption:=下午好,您已成功登錄!;
//顯示登錄用戶信息、登錄日期和時間
NameEdit.Text:=LoginUser.UserName;
FullNameEdit.Text:=LoginUser.UserFullName;
GroupEdit.Text:=IntToStr(LoginUser.UserGroup);
DisplayDateEdit.Text:=DateToStr(Date);
DisplayTimeEdit.Text:=TimeToStr(Time);
end;
表3主窗體中組件屬性設置
組件 屬性 設置 Form1 Caption Name MainForm Position poScreenCenter GroupBox1 Caption 用戶信息 Label1 Caption 用戶名稱: Label2 Caption 用戶全名: Label3 Caption 用戶組號: Label4 Caption 登錄日期: Label5 Caption 登錄時間: Edit1 Name NameEdit Edit2 Name FullnameEdit Edit3 Name GroupEdit Edit4 Name DisplayDateEdit Edit5 Name DisplayTimeEdi
8.數據模板。選擇File/NewData Module建立數據模板LogDataModule,放入一個Ttable組件,如圖1。屬性 按表4設置,命名其單元為MD.pas,存入Login目錄。
組件 屬性 設置 Table1 DatabaseName UserInfo Name UsersTable TableName Users.DB
9.創建注冊窗體。選擇File/New Form創建一個新窗體,並加入組件TLabel、TEdit和TbitBtn各兩個。窗體和組件屬性按表5設置,命名其單元為Login.pas,存於Login目錄。
表5注冊窗體中組件屬性設置
組件 屬性 設置 Form2 ActiveControl UserNameEdit Caption 請注冊 Name LoginDialogForm Position poScreenCenter Label1 Caption 用戶: Label2 Caption 密碼: Edit1 Name LoginNameEdit Text Edit2 Name PasswordEdit PasswordChar * Text BitBtn1 Caption 注冊(&L) Enabled False Kind bkOK Name LoginBitBtn BitBtn2 Caption 取消(&C) Enabled True Kind bkCancel Name CancelBitBtn
10.選擇File/New命令,從NewItems 的New頁中選擇Unit項建一個無窗體單元Addition.pas存入Login目錄,在其interface段輸入下列語句:
usesClasses,Forms,Sysutils;
type
TApplicationUser=class(TComponent)
private
FUserName:string;
FFullName:string;
FUserGroup:Integer;
public
propertyUserName:stringreadFUserNamewrite FUserName;
propertyUserFullName:stringreadFFullName writeFFullName;
propertyUserGroup:IntegerreadFUserGroup writeFUserGroup;
end;
var
LoginUser:TApplicationUser;
在implementation段加入下列語句:
initialization
LoginUser:=TapplicationUser.Create(Application);
11.創建注冊窗體(LoginDialogForm) 的OnCreate事件處理程序。在private段中聲明CountDown為Integer變量,作為計數器,並將下述語句插入begin與end之間:
CountDown:=3;//允許嘗試注冊3次
12.建立用戶名輸入框(LoginNameEdit) 的OnChange事件處理程序,使窗體LoginDialogForm創建時注冊按鈕為灰色,用戶輸入登錄名後才可用。不難實現,源代碼略。
13.創建注冊過程。雙擊注冊按 鈕(LoginBitBtn),在begin和end之間輸入其OnClick事件處理程序代碼:
ModalResult:=mrNone;
try
Session.AddPassword(UserPassword);
LogDataModule.UsersTable.Open;
//注冊信息處理
ifnotLogDataModule.UsersTable.FindKey
([LoginNameEdit.Text,PasswordEdit.Text]) then
begin
//處理注冊次數
dec(CountDown);
ifCountDown=0thenModalResult:=mrCancel else
begin
MessageBeep($FFFF);
Application.MessageBox(請您重試一次!,無效注冊信息,mb_iconstop+mb_OK);
//重設輸入焦點
LoginNameEdit.SetFocus;
end;
exit;
end;
//檢查注冊允許值
ifnotLogDataModule.UsersTable.FieldByName(Enabled).AsBoolean then
begin
MessageBeep($FFFF);
Application.MessageBox(抱歉,您不能進入系統!,使用權限終止,mb_iconexclamation+mb_OK);
ModalResult:=mrCancel;
exit;
end;
//獲取注冊用戶信息
withLogDataModuledo
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;
14.在Main.pas單元的uses中 加入Addition,在Login.pas單元的implementation段增加uses 語句:
usesMD,Addition;
15.打開過程文件Register.dpr, 在uses語句中加入Controls,將Application.run;改為下列語句,只有注冊成功時才啟動系統,同時釋放注冊窗體,以確保安 全和減少內存占用。
ifLoginDialogForm.ShowModal=mrOKthen
begin
LoginDialogForm.Free;
Application.Run;
end;
16.編譯、運行。注冊窗口見圖2, 輸入用戶名和密碼後點注冊按鈕。
如果注冊信息有誤,系統出現提 示框,允許重新注冊,見圖3。若三次嘗試均不成功,注冊窗口將保護性關閉。
訪問權已被管理員終止的用戶(Enabled 的值為False),例如用戶User1以口令CCCCCC注冊至用戶組1,系統拒絕進入。
注冊成功後將啟動系統主程序。 例如用戶Supervisor以口令AAAAAA注冊。
上述方案具有以下特點:
1.Supervisor用戶具有至高無 上的權利,由系統創建,不能刪除,僅Password和Fullname字段的值允許自行修改。主要負責系統維護和用戶帳戶管理等工作,是系統的永久性特權用戶。
2.確保用戶帳戶表Users.DB的 安全致關重要,本方案采用了較為可靠的關鍵性技術,就是注冊過程(見步 驟13)中try…finally…end結構的應用。僅當用戶按下注冊按鈕時,注冊模塊轉送表Users.DB的密碼並將其打開,以處理 注冊信息。而無論成功與否,在finally部分都能及時關閉表Users.DB,並立即清除內存中的密碼。
3.用戶帳戶管理模塊設在主程序中,完成表Users.DB的維護功能,包括建立用戶帳戶和用戶組,增、刪用戶,分配訪問權限等。只有Supervisor或其授權用戶才可進入。
4.組帳戶管理:用戶按不同級 別分組,再按組進行權限分配,以簡化管理。如系統可根據登錄用戶所屬的用戶組,十分方便地屏蔽相應菜單項,以達到限制用戶使用權限的目的。對用戶群大的系統,此項技術的優越性尤為顯著。
5.默認帳戶限制:建立用戶帳戶時,系統默認其Group=3,僅具備浏覽有限信息之權限,不致因管理員一時疏忽使新建用戶越權使用,危及系統安全。
6.單獨帳戶限制:用戶注冊時,必須提供完整的個人有效信息才能進入系統。
7.注冊允許限制:管理員可隨時取消或恢復單個用戶、用戶組甚至系統所有用戶(Supervisor除外)的注冊權限,只需設置注冊允許字段Enabled的值為False或True。
8.非法入侵限制:三次注冊嘗 試不成功便保護性關閉注冊窗口,以防非法非法入侵者無限制嘗試。
本文介紹了應用軟件注冊安全性 問題的綜合解決方案,容易實現,便於擴充如增加注冊時間限制和記帳收費功能等,可建立較完善的注冊安全機制,適合大型商用軟件開發。