2013-08-26 53 views
6

我想在運行時動態地在代碼中調整機器密鑰,用於IIS託管的ASP.NET MVC 4網站。代碼中的ASP.NET機器密鑰設置密鑰

機器密鑰,加密和驗證密鑰以及要使用的算法存儲在數據庫中。我不想從web.config文件中讀取值,而是想在應用程序啓動過程中注入這些值,並讓系統使用這些值。

有什麼辦法可以完成,而不必改變web.config(只改變內存配置)?

我試過訪問配置部分,但它被標記爲只讀,並且也被密封,所以我不能覆蓋IsReadOnly()。但是,對我而言,有一個setter這是一個指示器,可能有辦法刪除只讀標誌。

var configSection = (MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey"); 
if (!configSection.IsReadOnly()) 
{ 
     configSection.ValidationKey = _platformInfo.MachineKey.ValidationKey; 
     configSection.DecryptionKey = _platformInfo.MachineKey.EncryptionKey; 
     ... 
} 

有沒有什麼辦法可以做到這一點? 我能看到的唯一選擇是使用像AppHarbor這樣的自定義方法,但是如果可能的話,我寧願堅持內置方法。

如果有人問我爲什麼要這樣做,原因是, 這是針對大量相同的網站在網站羣中運行。因此,具有非自動生成的密鑰是必須的(每個服務器上必須是相同的)。每個網站也應該被隔離,不應該共享相同的密鑰。由於所有網站的物理表示都相同,因此它們共享相同的物理位置。這就是web.config文件不能包含應用程序特定設置的原因。

編輯:如果確實無法完成,至少應該確認一下。如上所述,人們可以使用自定義身份驗證和加密方法來避免完全使用機器密鑰設置。謝謝。

回答

5

一旦Web應用程序啓動,就沒有辦法以編程方式設置它。但是,仍然有可能實現您的目標。

如果每個應用程序在其自己的應用程序池正在運行,如果每個應用程序池都有自己的身份,然後在applicationHost.config檢查出CLRConfigFile開關。您可以使用此每個應用程序池來注入新的配置級別。有關如何使用此示例的示例,請參閱http://weblogs.asp.net/owscott/archive/2011/12/01/setting-an-aspnet-config-file-per-application-pool.aspx。您可以在每個應用程序池的自定義CLR配置文件中設置顯式且唯一的system.web/machineKey >元素。

這是Azure網站,GoDaddy和其他需要在每個應用程序基礎上設置默認顯式機器密鑰的主機所使用的機制。請記住,要爲將訪問它的應用程序池適當地ACL每個目標.config文件。

+0

感謝了很多,幫助我(和希望其他人也是如此)。通常較大的網站使用單獨的應用程序池。但較小的網站可能共享應用程序池。但正是我所需要的,因爲我可以圍繞這個建立起來。 – michael81

+0

定製CLR配置文件的結構應該是「/configuration/system.web/machineKey」嗎?有沒有辦法顯示或測試應用程序上的實際machineKey值,以確認自定義CLR配置文件實際上是否正確生效? – John

+0

是的。您可以使用ConfigurationManager.GetSection(「system.web/machineKey」),將返回的對象轉換爲MachineKeySection,並查看掛起的屬性以驗證您的更改是否正確拾取。 – Levi

2

這是醜陋的,但我可以使用反射來暫時從配置部分只讀位,設置的加密密鑰,然後將其還原:

var getter = typeof(MachineKeySection).GetMethod("GetApplicationConfig", BindingFlags.Static | BindingFlags.NonPublic); 
var config = (MachineKeySection)getter.Invoke(null, Array.Empty<object>()); 

var readOnlyField = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 
readOnlyField.SetValue(config, false); 

config.DecryptionKey = myKeys.EncryptionKey; 
config.ValidationKey = myKeys.ValidationKey; 

readOnlyField.SetValue(config, true);