在配置系統中安全地存儲數據是一個難以解決的問題早年當我在 ASPNET 團隊的時候這一特定功能(安全地存儲連接字符串)好像不會得到實現了它被無數個問題(如密鑰存儲)團團包圍阻礙了解決之路幸運的是這個問題不但最終得到了解決而且還融入到 ASPNET 強大的最新 API 組合中從而使您得以通過編程方式管理 ASPNET 配置文件
不過在深入探究 ASPNET 之前讓我們先研究一下這個問題了解一下 ASPNET x 中的各種解決方案只要您用過 ASPNET那麼您無疑會理解在 nfig 文件中存儲共享設置的好處例如您不必在每次創建新數據庫連接時都指定連接字符串而是可以將該字符串存儲在 ASPNET 配置文件的 <appSettings /> 節中這樣就可以通過 ConfigurationSettingsAppSettings 屬性訪問連接字符串下面是一個 <appSettings/> 節的示例
<?xml version= encoding=utf ?>
<configuration>
<appSettings>
<add key=ConnectionString
value=server=;database=demo;uid=db;pwd=*u%a />
</appSettings>
</configuration>
這樣每當您需要更改連接字符串時只需打開該文件執行更改即告完成
從傳統 ASP 轉向 ASPNET 的許多開發人員都對此功能深有體會因為大多數全局值都是以應用程序變量的形式存儲的實際上對於 ASPNET x在 <appSettings/> 中存儲連接字符串是一種推薦的做法還有一點也值得注意就是您也可以在 <appSettings/> 中存儲其他常用數據包括 LDAP 路徑常用應用程序設置以及應用程序所需要的其他數據<appSettings/> 的目標是簡化自定義配置節處理程序的編寫這是一項與 ASPNET 配置系統交互的更高級的技術自定義配置節處理程序允許您在配置系統內創作和處理自己的 XML 節
您也許已經注意到在 <appSettings/> 中存儲的內容沒有加密而是以純文本的形式存儲<sessionState/> 節也是如此該節支持在進程外存儲 Session 數據一種備選的存儲方式是使用 SQL Server?並在 <sessionState/> 配置位置中以純文本形式存儲憑據
等一等您不能這樣做
在 <appSettings/> 中存儲連接字符串的缺點是不能保證安全性因為該文件沒有經過加密也沒有經過編譯並不是說編譯配置信息就會對增強安全性有所幫助DVD 制造商使用基於密鑰的加密方法來保護知識產權方法是簡單地讓 DVD 播放器軟件供應商將解密密鑰存儲在他們的編譯代碼中某些黑客編寫的一小段代碼會輕而易舉地找到解密密鑰我們常常會在個人網絡日志中看到這樣的帖子有人想弄清某種東西在 Microsoft? NET Framework 中的工作機理這時就會有人建議試試 Reflector
ASPNET — 更好地保守秘密
在 ASPNET 中如果沒有額外的自定義代碼則無法在配置文件中安全地存儲連接字符串ASPNET 團隊在 ASPNET 中解決了這個問題方法是對幾個配置條目啟用加密該解決方案是通過 Windows 數據保護 API (DPAPI) 完成的從而能夠加密下列配置條目
<identity/> 用來存儲 ASPNET 輔助進程的 Windows? 標識以供模擬之用
<processModel/> 用來控制在其下執行 ASPNET 輔助進程的 Windows 帳戶IIS 中不使用(請參閱以下注釋)
<sessionState/> 具體包含 stateConnectionString 和 sqlConnectionString 屬性用於控制 ASPNET 對進程外狀態服務器的驗證方式
需要注意的很重要的一點是IIS (Windows Server? 附帶的 Web 服務器)提供了它自己的輔助進程管理子系統而 ASPNET 會順從該系統因此ASPNET 在由 IIS 托管時配置系統中的有些輔助進程設置將不被使用
隨 ASPNET 提供了名為 aspnet_setregexe 的工具用以加密配置文件中的數據並將解密密鑰存儲在 Windows 注冊表項中得到的注冊表項具有一個訪問控制列表 (ACL)該列表配置為限制有權訪問該密鑰的 Windows 帳戶知識庫文章 Q如何使用 ASPNET 實用工具加密憑據和會話狀態連接字符串中詳細介紹了這項技術
不過這個解決方案也有一些缺點它破壞了 ASPNET 團隊所鐘愛的 xcopy 部署該功能允許在無需訪問服務器的情況下部署 ASPNET 應用程序運用上文提到的技術開發人員或系統管理員必須具有本地計算機的訪問權限才能運行命令行工具進而加密配置數據並將密鑰存儲在注冊表中
ASPNET 秘密s
接下來我們可以開始討論該團隊為s在 ASPNET 中解決這一問題而做的所有工作了這次又有一個用於管理配置數據加密的命令行工具aspnet_regiisexeAspnet_regiisexe 存在於 ASPNET 的早期版本中主要用於手動向 IIS 注冊 ASPNET例如使用它向 IIS 添加 aspnet_isapidll 以及配置 ASPNET 應用程序使用的腳本目錄您可在 \Windows\MicrosoftNET\Framework\版本號\ 目錄中找到此工具
使用 aspnet_regiisexe 加密配置節的過程同它所生成的結果一樣撲朔迷離!請看圖 中 aspnet_regiisexe /help 的執行結果您就明白我的意思了

正如您所看到的那樣除非您非常熟悉安全術語否則您很快就會被大量的選項和各種設置弄的眼花缭亂不幸的是雖然功能強大但各種工具十分混亂現在我們暫不研究 aspnet_regiisexe 的使用方法先來看一個 ASPNET 示例頁面該頁面使用新的配置 API 來實現配置節的加密此頁面即 ConnectionEncryptionaspx(可以從 MSDN?Magazine 網站上獲得)包含一個 GridView用所有配置節的列表填充如圖 所示

在研究 ConnectionEncryptionaspx 內部的工作方式之前先看看這個頁面的結果但是先提出一個警告使用本工具要求托管 ASPNET 的進程對當前應用程序的 nfig 文件具有寫入權限默認情況下IIS 中運行的 ASPNET 應用程序沒有必要的權限不過托管在 ASPNET Development Web Server 中的應用程序使用已登錄用戶的權限集運行您在此處看到的該工具的所有用法都是在 ASPNET Development Web Server 中顯示的建議您在全面了解更改 IIS 權限設置所帶來的影響的情況下再執行更改
下面是 nfig 中用於存儲連接字符串的全新 <connectionStrings> 節的示例條目<connectionStrings> 節與 <appSettings> 節幾乎相同目前建議在前者中存儲連接字符串數據因為有新的 API 可以專門處理散布在 ASPNET 中的連接字符串
<connectionStrings>
<add name=Northwind providerName=SystemDataSqlClient
connectionString=Server=localhost;Integrated
Security=True;Database=Northwind />
</connectionStrings>
請注意在這種情況下仍然使用 Windows 驗證連接到數據庫
單擊 ConnectionEncryptionaspx 中的 Encrypt(加密)鏈接將 nfig 中連接字符串的值更改為如圖 中所示的內容加密後ConnectionEncryptionaspx 頁面會將該條目的狀態報告為已加密(鏈接會更改為Decrypt(解密)正如您在下圖中所見)

既然頁面已經生效讓我們來看一下代碼請看 ConnectionEncryptionaspxcs 中的第 行在 Page_Load 中當新的 ASPNET WebConfigurationManager 類檢索到本地路徑的 Configuration 類的實例時即填充 GridView
Configuration config =
WebConfigurationManagerOpenWebConfiguration(RequestApplicationPath)
使用從配置變量中檢索到的數據填充數組列表然後將其綁定到 GridView源中的大多數其他方法(請參閱下載的代碼)用於與實際數據綁定操作有關的業務邏輯規則如確定節的范圍和狀態(加密或取消加密)當單擊 Encrypt(加密)或 Decrypt(解密)鏈接時GridView_RowCommand 事件中便會發生神奇的事情當 GridViewCommandEventCommandName 的值為Encrypt(加密)時執行以下代碼
sectionSectionInformationProtectSection(
DataProtectionConfigurationProvider)
configSave()
當 GridViewCommandEventCommandName 的值為Decrypt(解密)時則執行以下代碼
sectionSectionInformationUnprotectSection()
configSave()
這樣就將加密和解密數據的實際工作轉交給了提供程序一個內置提供程序是 DataProtectionConfigurationProvider它使用內置的 DPAPI 來存儲安全數據這與 ASPNET 命令行工具所使用的相同
您應該注意加密數據時可以指定提供程序但解密時卻不需要指定提供程序(如果為 ProtectSection 提供的是 null 或空字符串則將使用在配置文件的 configProtectedData 節中指定的默認提供程序)這是因為 API 將另一條目寫入了配置文件中該條目用於指定所使用的加密保護提供程序
<connectionStrings configProtectionProvider=
DataProtectionConfigurationProvider>
<EncryptedData></EncryptedData>
</connectionStrings>
此配置條目不僅供 API 用以確定如何解密各個節而且在 ASPNET 需要將值(如連接字符串)讀入內存但必須先加以解密時供 ASPNET 在內部使用
ASPNET 的新增加密功能的一大優點是您不但可以加密許多內置配置節還可以編寫自定義的加密提供程序!提供程序是 ASPNET 中一個令人驚歎的新擴展模型它使得開發人員能夠實現他們自己的核心功能如成員身份個性化等等此外鑒於配置加密的實現方式自定義配置節也可以輕松得到加密因而對數據的保護不會象 ASPNET 中那樣僅僅局限於少數配置節
說點更高明的秘密
關於加密機密數據的專欄如果不提出幾條警告就不算是完整的專欄首先如果能避免保密就盡量避免保密如果您使用的是 SQL Server而且不想在配置系統中存儲敏感的連接字符串信息則使用 SQL Server 附帶的集成驗證Windows 驗證用於應用服務器與數據庫之間的連接利用此技術與 SQL Server 之間的連接會直接通過 Windows 進行驗證和授權使用 Windows 驗證時SQL Server 會向驗證服務器(無論本地還是遠程的)請求令牌該令牌包含用戶的安全標識符 (SID) 及其他信息然後將這些信息與 SQL Server 所維護的列表進行比較確定是准許還是拒絕訪問配置文件中不存儲密碼或用戶名
另外一件需要切記的事情是僅僅安全存儲了配置文件中的數據並非意味著您可以逃開各種各樣的攻擊任何稱職(安全雙關語)的攻擊者只要他獲得了訪問您的服務器上的 nfig 文件的足夠權限都可能會對您造成巨大危害獲得系統訪問權限能夠處理 nfig 的攻擊者可以執行其他操作來操縱數據庫而無需知道連接字符串是什麼因此安全存儲您的連接字符串或其他應用程序數據只是防線之一另外一項有效防御措施是使用存儲過程並且對那些有權訪問您的數據庫的帳戶設置更加嚴密的控制例如如果存在 SQL 注入漏洞加密的連接字符串將毫無價值(有關 SQL 注入攻擊的詳細信息請參閱 /msdnmag/issues///SQLInjection)
我曾構建並運行過很多高訪問量的網站(如/)因此我受到攻擊的機率並不比常人更低一個常見的特征是攻擊常常與最初的漏洞毫無關系攻擊者不會通過最初漏洞攻擊而是會努力保護通過最初的漏洞而制造的後門
結束語
雖然 ASPNET 的任一版本都可以保護 ASPNET 應用程序中的機密數據但這在 ASPNET 中較容易實現而在 ASPNET 中更是輕而易舉使用 ASPNET 配置加密不再是亡羊補牢它已經內置於新的配置 API 之中使用 ASPNET 您不但可以使用 aspnet_regiisexe 工具來加密配置節還可以編寫您自己的自定義代碼(以及自定義提供程序如果需要)來加密和解密配置數據
From:http://tw.wingwit.com/Article/program/net/201311/11990.html