Laden...

ASP.NET Core 2 ConnectionString aus appsettings.json lesen und in Registrierung übergeben?

Erstellt von Olii vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.949 Views
O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren
ASP.NET Core 2 ConnectionString aus appsettings.json lesen und in Registrierung übergeben?

Hallo, ich habe in einem Microsoft Artikel (den ich leider nicht mehr finde) gelesen, dass z.B. DB ConnectionStrings in der Datei appsettings.json gespeichert werden sollen, da diese dort wohl sicher Verschlüsselt werden:


"connectionStrings":{
    "appDbConnection": "Server=127.0.0.1;Port=5433;Database=peepconnect;UserId=postgres;Password=admin;"
  }

Dann natürlich ein einfaches IDBContext/DBContext erstellt wie folgt:


public interface IDBContext
    {
        string _connectionString {get;}
    }


public class DBContext : IDBContext
    {

        public DBContext(string connectionString)
        {
            _connectionString = connectionString;
        }

        public string _connectionString { get;}
    }

Das was ich nun sehr interessant finde ist die Registrierung. Dazu habe ich mehrere Wege gesehen und mir eine davon mal raus genommen:

Der Weg funktionierte sofort ohne Probleme:


services.AddTransient<IDBContext>(provider => new DBContext(this.Configuration.GetConnectionString("appDbConnection")));

Meine Frage ist es nun ob das wirklich der richtige Weg ist, bzw. ob dass hier vielleicht sogar sehr unschön und unsauber ist?

1.029 Beiträge seit 2010
vor 4 Jahren

Hi,

da hast du etwas falsch verstanden.

Die normale appsettings.json ist und wird NICHT verschlüsselt und sollte entsprechend auch eigentlich keine wirklichen Geheimnisse enthalten, sofern andere User mit Zugriff auf den Server diese Geheimnisse nicht kennen dürfen. Hierfür verwendet man z.B. UserSecrets - siehe z.B: https://www.twilio.com/blog/2018/05/user-secrets-in-a-net-core-web-app.html

Zur Schönheit:
Public Properties beginnen eigentlich nicht mit einem Unterstrich. Das Hinzufügen des Services selbst ist schon in Ordnung - es gibt allerdings auch die Methode "AddDbContext", siehe z.B. https://stackoverflow.com/questions/44466885/asp-net-core-dbcontext-injection

LG

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Achso okey, dann hatte ich das falsch im Kopf. Vielen Dank, ich lese mir die Beiträge mal durch.

Note: Ich habe einen der Links gefunden die ich dazu gerade nicht finden konnte, wo jemand das ebenfalls dort gespeichert hat. Deshalb dachte ich es wäre wohl gängig gewesen 😄

store connectionString in appsettings.json

1.029 Beiträge seit 2010
vor 4 Jahren

Hi,

naja - das Config-Modell erlaubt das selbstverständlich, da das Config-Framework hier diverse Quellen aggregiert die sich gegenseitig auch noch überschreiben können. Das können Umgebungsvariablen, json-Files, UserSecrets und noch zig andere Sachen sein (sogar eigene). Für einen ConnectionString ohne Passwort hätte ich damit wahrscheinlich nicht mal ein Problem mit - mit Passwort allerdings sieht die Sache anders aus 😉

Zumal man auch berücksichtigen sollte, dass die appsettings.json und deren Pendants eigentlich Teil der Quellcodeverwaltung sein müssen. (Für private Projekte nutze ich hier gerne z.B. eine appsettings.secret.json die per globalem gitignore ausgeschlossen ist)

LG

O
Olii Themenstarter:in
76 Beiträge seit 2017
vor 4 Jahren

Achso okey, danke für die Informationen 😄

Ich habe mir die Beiträge auch mal angesehen und ein weiteren ähnlichen gefunden zu User Secrets

User secrets

In diesem Artikel wird unter anderem folgendes erwähnt:

The user secrets are saved as a json file located in %APPDATA%\microsoft\UserSecrets&lt;userSecretsId>\secrets.json in Windows, ~/.microsoft/usersecrets/<userSecretsId>/secrets.json on Linux and Mac. This file is not encrypted, and for this reason there’s a warning in the documentation saying that you should not use it in production. Same applies to environment variables.

Even though this is the case, the only recommended “production-ready” solution is Microsoft Azure Key Vault. If you don’t use Azure, or don’t want to pay for Azure Key Vault you’ll either have to encrypt the secrets yourself or find another solution (currently I don’t know of any that I can recommend)

Wo der Artikelersteller behauptet das auch User Secrets nicht für die Produktion geeignet sind. Also für den live Betrieb. Und das, zumindest er, außer Azure keine weitere Möglichkeit sieht.

Wäre es dann vielleicht wirklich Sinnvoll Secrets zu benutzen aber den gespeicherten Wert z.B: für den ConnectionString selber zu ver- und entschlüsseln? Oder wie würdet ihr das machen wenn so etwas mal live gehen sollte?

1.029 Beiträge seit 2010
vor 4 Jahren

Hi,

sry - dass auch die UserSecrets nicht so verwendet werden sollten war mir nicht bewusst.

Faktisch geht es um Folgendes bei den UserSecrets:
Es soll lediglich vermieden werden, dass wichtige Informationen wie Passwörter & Co. Teil der SourceControl werden.

Wenn du die Passwörter auf dem Server verschlüsselt haben möchtest - dann kann man dafür DataProtection verwenden - siehe https://stackoverflow.com/questions/40131672/storing-production-secrets-in-asp-net-core

Faktisch hilft das in meinen Augen nicht sonderlich viel weiter - letztlich kann's doch jeder Admin haben der's will. Ich für meinen Teil verwende im Development eine appsettings.secret.json - in der Produktion wird jedoch mit Docker gearbeitet - und da werden dem Container jeweils Umgebungsvariablen mitgegeben, welche mangels einer appsettings.secret.json auch nicht überschrieben werden. Dies zu verschlüsseln halte ich persönlich für unnötig, denn:
a) Muss der Admin das auch anpassen und lesen können
b) Selbst wenn du verschlüssselst - liegen Key und Secret immer noch beieinander - sicherer wird's nicht

LG

Edit:
Hab's auch schon mal beim Deployment einer ASP.NET-Anwendung eines unserer Dienstleister gesehen - da wurde dann in der app.config ein verschlüsselter Key hinterlegt, dessen Entschlüsselung (natürlich) im Code stattfand. Da ich diesen Key auch kennen wollte - habe ich kurz den entsprechenden Verweis importiert - und den Key so ausgelesen. Effekt der Verschlüsselung? Nicht vorhanden.

16.834 Beiträge seit 2008
vor 4 Jahren

Dass irgendwas in der Config verschlüsselt wird, ist wie bereits geklärt nicht korrekt.
Dass die Config aber der korrekte Platz für Connection String ist, das stimmt.

Das Konfigurationsmodell ist folgendermaßen gedacht:
In der appsettings.json ist maßgeblich für die Struktur der Konfigration verantwortlich - man hinterlegt hier aber in produktiven Anwendungen nur default Werte - dazu gehören aber keine Datenbankverbindungen oder Credentials.

Eine appsettings.json kann daher folgendermaßen aussehen (kopiert aus einer echten Anwendung von mir):

{
  "ConnectionStrings": {
    "UserDatabase": "",
    "CachingDatabase": ""
  }
  "Serilog": {
    // "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.ApplicationInsights" ],
    "WriteTo": [
      {
        "Name": "ApplicationInsights",
        "Args": {
          "restrictedToMinimumLevel": "Information",
          "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
  },

Wir sehen hier also eine Default Config für Serilog und Platzhalter für die Datenbankverbindungen.

Damit man beim Entwickeln arbeiten kann, legt man sich eine appsettings.development.json an.
Hier hinterlegt man sich die Datenbankverbindung für das lokale Arbeiten.

{
  "ConnectionStrings": {
    "UserDatabase": "ConnectionString",
    "CachingDatabase": "ConnectionString"
  }
}

Es funktioniert nun so, dass die Konfigurationsmiddleware zunächst die appsettings.json liest und danach durch die Werte in appsettings.Development.json überschrieben werden - beim Entwickeln.
D.h. die Platzhalterwerte werden gesetzt.

In produktiven Umgebungen werden die ConnectionStrings nun in der Ausführenden Umgebung hinterlegt; d.h. in Azure in den Application Settings, im IIS im COnfiguration Edtor, in Docker durch die Umgebungsvariablen.

Diese Werte verhalten sich dann ähnlich wie Development:
zuerst wird appsettings.json geladen und anschließend die Werte aus der Azure/IIS/Docker Umgebung gezogen.

6.911 Beiträge seit 2009
vor 4 Jahren

Hallo,

Konfigurationsmiddleware

Die gibt es nicht (zumindest per Standard ASP.NET Core). ConfigurationBuilder hingegeben schon.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

16.834 Beiträge seit 2008
vor 4 Jahren

Die gibt es nicht (zumindest per Standard ASP.NET Core). ConfigurationBuilder hingegeben

Im gesamten Spektrum gibt es mehrere Builder und mehrere Middlewares.
Wir haben WebHostBuilder, HostBuilder, ConfigurationBuilder, ServiceBuilder....

Und wir haben Middlewares bzw. Pipelines. Configuration, Logging, Request....

Die Reihenfolge, wie Konfigurationen verarbeitet werden, ist dabei Teil des WebHostBuilders (mit ASP.NET 3 nur noch HostBuilder) _> Configuration Builder.
Jede gefundene, gematche Konfiguration durchläuft dann eine Pipe.

Daher: ja, es gibt sehr wohl eine Middleware/Pipeline, wie die Konfiguration verarbeitet wird.

6.911 Beiträge seit 2009
vor 4 Jahren

Hallo,

ja, es gibt sehr wohl eine Middleware/Pipeline, wie die Konfiguration verarbeitet wird.

wenn wir unter Middleware die ASP.NET Core Middleware verstehen -- davon ist im Kontext hier auszugehen -- so hat die Konfiguration damit nichts zu tun.

Configuration Builder.
Jede gefundene, gematche Konfiguration durchläuft dann eine Pipe.

Mag sein, aber nicht in ASP.NET Core, wie im Code zu sehen ist 😉
Im ConfigurationBuilder ist es im Wesentlichen eine List<IConfigurationSource> zu der Einträge hinzugefügt werden um dann im Build (gem. Erbauer (Entwurfsmuster), daher auch der Suffix im Namen) die ConfigurationRoot zu erstellen. Dabei spielt eben die Liste eine entscheidende Rolle, da so über die Reihenfolge des Hinzufügens die resultierenden Config-Werte ermittelt werden (kurz: das später Hinzugefügte überschreibt das vorherige). Mit Pipe hat das nichts zu tun, da es eine (triviale) Iteration vom Listenende zum Listenanfang ist.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"