2013-08-26 8 views
6

Ich möchte die Maschinenschlüssel dynamisch in Code während der Laufzeit für eine von IIS gehostete ASP.NET MVC 4-Website anpassen.ASP.NET Maschinentaste Schlüssel im Code

Die Maschinenschlüssel, Verschlüsselungs- und Validierungsschlüssel sowie zu verwendende Algorithmen werden in einer Datenbank gespeichert. Anstatt die Werte aus der Datei web.config zu lesen, möchte ich diese Werte beim Start der Anwendung injizieren und sie stattdessen vom System verwenden lassen.

Gibt es eine Möglichkeit, dies zu erreichen, ohne die web.config überhaupt ändern zu müssen (um nur die In-Memory-Konfiguration zu ändern)?

Ich habe versucht, auf den Konfigurationsabschnitt zuzugreifen, aber es ist als readonly markiert und ist auch versiegelt, so dass ich IsReadOnly() nicht überschreiben kann. Allerdings gibt es eine setter, die ein Indikator für mich ist, dass es möglicherweise eine Möglichkeit gibt, das Readonly-Flag zu entfernen.

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

Gibt es eine Möglichkeit, dies zu erreichen? Die einzige Alternative, die ich sehen kann, ist eine benutzerdefinierte Methode wie AppHarbor verwenden, aber ich würde lieber mit dem eingebauten Ansatz bleiben, wenn es überhaupt möglich ist.

Falls jemand fragt, warum ich das machen möchte, ist der Grund, dies ist für eine große Anzahl von identischen Websites in einer Webfarm ausgeführt. Daher ist die Verwendung von nicht automatisch generierten Schlüsseln ein Muss (muss auf jedem Server identisch sein). Auch sollte jede Website isoliert sein und sollte nicht die gleichen Schlüssel teilen. Da alle Websites in ihrer physischen Darstellung identisch sind, teilen sie sich denselben physischen Standort. Aus diesem Grund kann die Datei web.config keine anwendungsspezifischen Einstellungen enthalten.

Edit: Es wäre sehr hilfreich zu bestätigen, zumindest, wenn es einfach nicht möglich ist. Wie gesagt, kann man benutzerdefinierte Authentifizierungs- und Verschlüsselungsmethoden verwenden, die es vermeiden würden, die Maschinenschlüsseleinstellungen insgesamt zu verwenden. Vielen Dank.

Antwort

5

Es gibt keine Möglichkeit, dies programmgesteuert festzulegen, sobald die Webanwendung gestartet wird. Es ist jedoch immer noch möglich, Ihr Ziel zu erreichen.

Wenn jede Anwendung in einem eigenen Anwendungspool ausgeführt wird, und wenn jeder Anwendungspool hat seine eigene Identität, dann die in applicationHost.configCLRConfigFile Schalter überprüfen. Sie können diesen Pool pro Anwendung verwenden, um eine neue Konfigurationsstufe hinzuzufügen. Ein Beispiel für die Verwendung dieses Beispiels finden Sie unter http://weblogs.asp.net/owscott/archive/2011/12/01/setting-an-aspnet-config-file-per-application-pool.aspx. Sie könnten ein eindeutiges und eindeutiges <system.web/machineKey> Element in der benutzerdefinierten CLR-Konfigurationsdatei jedes Anwendungspools festlegen.

Dies ist derselbe Mechanismus, der von Azure-Websites, GoDaddy und anderen Hoster verwendet wird, die standardmäßige explizite Maschinenschlüssel für einzelne Anwendungen festlegen müssen. Denken Sie daran, jede Ziel-CONFIG-Datei für den Anwendungspool, der auf sie zugreift, entsprechend zu ACLIEREN.

+0

dank viel, das mir hilft (und hoffentlich auch andere). Normalerweise verwenden die größeren Websites separate Anwendungspools. Aber kleinere Sites teilen möglicherweise einen Anwendungspool. Aber genau was ich brauche, wie ich das aufbauen kann. – michael81

+0

Sollte die Struktur der benutzerdefinierten CLR-Konfigurationsdatei "/configuration/system.web/machineKey" lauten?Gibt es eine Möglichkeit, den tatsächlichen ComputerKey-Wert in der Anwendung anzuzeigen oder zu testen, um zu bestätigen, dass die benutzerdefinierte CLR-Konfigurationsdatei tatsächlich ordnungsgemäß ausgeführt wurde? – John

+0

Ja. Sie können ConfigurationManager.GetSection ("system.web/machineKey") verwenden, das zurückgegebene Objekt an MachineKeySection übergeben und die davon abhängenden Eigenschaften betrachten, um zu überprüfen, ob Ihre Änderungen korrekt übernommen wurden. – Levi

2

Es ist hässlich, aber ich war in der Lage Reflexion zu verwenden, um vorübergehend den Nur-Lese-Bit aus dem Config-Abschnitt zu entfernen, die Schlüssel festgelegt, dann wiederherstellen:

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);