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

安全簡報:善用事件日誌提升應用程式可管理性

     編輯:關於.NET

資訊安全的三大核心支柱向來是機密性、完整性與可用性。提到可用性,開發人員往往直覺聯想到防禦阻斷服務攻擊等較易識別的威脅,但真正落實可用性遠不止於此。高可用性應用程式必須具備處理異常狀況的能力;當問題浮現時,管理員需能迅速鎖定解決方案。設計時納入可管理性考量的應用程式,通常擁有更高的可用性,主因在於管理員能時刻掌握系統運作狀況。更進一步地,優秀的可管理性應用程式在發生錯誤時,會提供具體可執行的排除建議給管理員,而非僅丟出供開發人員除錯用的堆疊追蹤資訊。

將 IT 專業人士視為軟體使用者

你或許聽聞過微軟倡導的動態系統管理計畫 (DSI)。此願景讓我們得以運用系統定義模型 (SDM) 與服務模型語言 (SML) 等工具,設計出更易部署、管理的應用程式。Visual Studio Team System 中的分散式系統設計師(早期代號 "Whitehorse")便是此方向的早期嘗試。然而,當前開發人員更迫切需要的是構建可管理系統的實務指引。

我近期與微軟開發人員兼技術布道師 David Aiken 深入交流,他對構建可管理軟體充滿熱情,並一針見血地指出:「開發人員應將 IT 專業人士視為其軟體的使用者。」我們在設計 Windows Forms 或網頁版面時投入大量心力,為何在設計寫入事件日誌的錯誤訊息時,卻不願付出同等努力?

David 的觀點極具說服力。IT 專業人士不僅是軟體使用者,更需在軟體整個生命週期中操作、管理系統。簡化他們的工作不僅關乎可用性,更能讓系統管理員成為產品忠實擁護者,助推下一版本銷售。目前真正重視可操作性的應用程式寥寥可數,這正是建立競爭優勢的關鍵領域。

過去幾年,微軟在構建更安全軟體(含威脅模型工具與藍圖)上取得長足進步。隨著安全控制趨嚴,重心似乎正轉向可管理性。或許在本文刊出時,你已能聽聞微軟推出運行狀況建模工具的消息。在此之前,讓我們先從最基礎的管理議題——事件日誌記錄——切入,探討如何在 Windows Server 2003 中更有效地運用 .NET Framework 的事件日誌功能。

深入理解事件日誌機制

Windows 事件日誌設計之初即秉持本地化與高效能原則。設計良好的應用程式日誌事件,應包含足夠文字說明問題並提供建議動作。這些文字多為本地化內容,因閱讀者可能是身處異國的遠端使用者。為讓你以母語閱讀日誌,可本地化的訊息文字並不實際儲存於日誌中,而是讀取時在本地端與日誌合併。實際文字儲存在讀者電腦上已本地化的資源 DLL 中,此做法同時縮減日誌檔案大小與網路流量。

.NET Framework 出現前,開發人員須自行建立並註冊資源 DLL,流程清晰但繁瑣。典型訊息範例:「使用連接字串 %2 連接資料庫 %1 失敗。請檢查資料庫是否可用。」此時僅事件 ID、來源、類型等中繼資料與參數(資料庫名稱 %1、連接字串 %2)寫入日誌。讀取時,Windows 載入本機訊息資源 DLL,依事件 ID 尋找本地化訊息,再合併參數顯示。

Windows 透過事件來源名稱對應登錄機碼,確定使用哪個資源 DLL。登錄機碼指向資源 DLL 路徑。早期 Win32 程式設計師需手動建立登錄項,.NET Framework 的 EventLog 類則封裝了這些細節。

.NET Framework 1.x 的事件日誌用法與限制

.NET Framework 1.x 中,EventLog 類提供基本事件日誌存取,試圖以簡化存取鼓勵使用。安裝時若程式碼具高權限,單行程式碼即可建立事件來源:EventLog.CreateEventSource("MyApp", "Application")。執行時若權限較低,無需建立資源 DLL 即可記錄事件:EventLog.WriteEntry("MyApp", "Testing 123")。

關鍵在於這兩個步驟:建立事件來源實際上是在建立登錄機碼,屬權限操作。若安裝時忽略此步,WriteEntry 會嘗試代為執行。以管理員身分執行測試代碼時可能成功,但實際以一般使用者帳號執行時會失敗。因此,務必在安裝期間建立事件來源。

若無對應資源 DLL 即嘗試寫入訊息,事件檢視器會顯示找不到事件描述的通知。Framework 的因應之道是:簡單呼叫 CreateEventSource 會將事件來源連結至預設訊息檔 EventLogMessages.dll,該檔包含 65,536 個描述,每個皆為 "%1" 佔位符。雖鼓勵使用日誌,卻違背本地化訊息與控制日誌大小的初衷。

.NET Framework 2.0:完整釋放事件日誌威力

幸運的是,.NET Framework 2.0 修正此問題,允許建立事件來源時註冊訊息檔,同時支援本地化類別與訊息,並縮減日誌訊息大小。新式註冊方式如下:

EventSourceCreationData source = new EventSourceCreationData("MyApp", "Application");
source.CategoryCount = 2;
source.CategoryResourceFile = "path to dll";
source.MessageResourceFile = "path to dll";
source.ParameterResourceFile = "path to dll";
EventLog.CreateEventSource(source);

雖技術上可保留三個資源 DLL,但大多數應用程式會將類別、訊息、參數三類資源整合在單一 DLL 中。

建立訊息檔與資源 DLL

為事件日誌建立資源 DLL,需先撰寫訊息檔(通常為 .mc 副檔名文字檔),再以訊息編譯器 mc.exe 處理。編譯器追蹤多個變數:MessageId 需針對每條訊息更新,Severity 可針對整個區段設定一次。訊息文字另起一行,以單獨一行的句號結束。支援多語言本地化,如:

MessageId=1003 SymbolicName=DatabaseConnectionFailed Language=English
Could not connect to SQL Server database %1. Reason: %2 .
Language=Spanish
No podía conectar con SQL Server database %1. Razón: %2 .

檔案頂部需定義語言:LanguageNames=(English=0x409:MSG00409) LanguageNames=(Spanish=0xC0A:MSG00C0A)。編譯後產生每種語言的 .bin 檔與引用它們的 .rc 資源檔。接著執行資源編譯器 (rc.exe) 產生 .res 檔,再用連結器 (link.exe) 產生 DLL:rc messages.rc && link /DLL /SUBSYSTEM:WINDOWS /NOENTRY /MACHINE:x86 messages.res。

關鍵細節:事件類別與 SymbolicName

訊息檔應包含已本地化的事件類別名稱,格式類似一般訊息,但為短名稱且 MessageId 必須從 1 開始連續。建立事件來源時,CategoryCount 指定為最高類別編號。SymbolicName 主要用於產生 C/C++ 標頭檔常數,對 .NET 開發人員目前用處不大,但若未來有工具能從訊息檔產生 Managed 類別定義,價值將大增。

參數機制

參數分兩類:最常見的是執行時填入的資料(如 %1、%2);另一類是從訊息檔分離常見字串(如應用程式名稱),使用 %%N 語法,N 為參數資源 DLL 中替換字串的 MessageId。

建立自訂日誌:避免污染應用程式日誌

IT 專業人士最反感應用程式在事件日誌大量記錄瑣碎資訊,淹沒關鍵訊息。執行追蹤、偵錯等資訊不應寫入應用程式日誌,而應導向自訂應用程式日誌。安裝程式中可建立自訂日誌,指定日誌名稱與不同的事件來源名稱:

EventSourceCreationData source = new EventSourceCreationData("MyApp Operational", "MyApp");
source.CategoryCount = 2;
source.CategoryResourceFile = "path to dll";
source.MessageResourceFile = "path to dll";
source.ParameterResourceFile = "path to dll";
EventLog.CreateEventSource(source);

執行時記錄事件:強類型封裝

如同建立資料存取層簡化資料庫操作,記錄事件也應建立輔助類別。範例中建立兩個類別:一個寫入應用程式日誌的管理事件,另一個寫入自訂日誌的操作事件。每個事件對應一個方法,強類型參數代表所需資料。例如記錄資料庫連線失敗:

public void DatabaseConnectionFailed(string dbName, string connectionString) {
    operationalLog.WriteEvent(
        new EventInstance(1003, 2, EventLogEntryType.Error),
        dbName, connectionString, new StackTrace(1));
}

WriteEvent 為 .NET Framework 2.0 新增方法,可傳遞參數填入訊息檔佔位符(如 %1)。此法提供豐富細節(資料庫名稱、連接字串、堆疊追蹤),故送至自訂操作日誌;同時向應用程式日誌發送更簡潔、可操作的訊息。

總結與展望

透過事件日誌等技術精心儀器化為操作設計的應用程式。將 IT 專業人士視為頭等使用者,有助確保系統穩定、減少停機。建立自訂事件日誌並集中非關鍵事件,可騰出應用程式日誌空間給可操作事件,讓 IT 人員迅速掌握恢復正常運作的方法。

現有事件系統(含 .mc 格式)多半神秘難懂。好消息是 Windows Vista 徹底重新設計內建事件系統,這將成為代號 "Longhorn" 的 Windows Server 一部分。基本概念未變,但新增許多強大功能,能記錄更豐富事件;取代訊息檔的新格式以 XML 儲存更多事件中繼資料,利於分析。下一期專欄將深入介紹新系統,敬請期待!

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