web-dev-qa-db-fra.com

Comment stocker correctement les chaînes de connexion dans les variables d'environnement pour la récupération par les applications ASP.Net Core MVC de production

Je travaille sur une application ASP.NET Core MVC et je rencontre un problème avec mes chaînes de connexion.

J'ai un ASPNETCORE_ENVIRONMENT variable définie sur Production sur mon serveur de production et ce dernier est un serveur Windows Server 2012R2 exécutant IIS. Le fichier DotNetCore.1.0.4_1.1.1-WindowsHosting.exe est également installé sur le serveur de production.

Pendant le développement, j'utilise UserSecrets pour conserver ma chaîne de connexion. Cela fonctionne correctement.

Pour la production, je veux mes chaînes de connexion dans des variables d’environnement sur mon serveur de production et c’est là que je rencontre un problème. Je soupçonne que c'est peut-être dans la façon dont je structure la variable d'environnement.

Lorsque j'essaie d'accéder à la base de données en production, un message d'erreur m'indique qu'il ne peut pas analyser la chaîne de connexion.

An exception occurred in the database while iterating the results of a query.

System.ArgumentException: Keyword not supported: '"server'.
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary`2 
parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary`2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)

Si je mets la chaîne de connexion dans appSettings.json, le serveur de production fonctionne correctement.

Donc, voici un exemple de mon appSettings.json fichier montrant la chaîne de connexion qui fonctionne en production;

{
  "ConnectionStrings": {
     "TestDb": "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"
  },

    ...
    ...
    ...
  }
}

Si je déploie ce appSettings.json fichier à la production, cela fonctionne bien.

Dans mon application ASP.Net Core, dans le fichier Startup.cs, j'ai les éléments suivants:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    if (env.IsDevelopment())
    {
        // For more details on using the user secret store see https://go.Microsoft.com/fwlink/?LinkID=532709
        builder.AddUserSecrets<Startup>();
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();

}

Si j'ai bien compris, le dernier constructeur.add ... répertorié a la priorité. Par conséquent, dans mon cas, si une chaîne de connexion existe dans l'environnement, elle doit avoir la priorité sur tout ce qui se trouve dans appsettings.

Donc, en production, si j'utilise le fichier appSettings.config suivant;

{
  "ConnectionStrings": {
     "TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production. "
  },

    ...
    ...
    ...
  }
}

Peu importe ce que j'ai comme valeur pour ConnectionStrings:TestDb dans ce appsettings.json fichier si j’ai une variable d’environnement pour la chaîne de connexion.

Ci-dessous figure la variable d'environnement que j'utilise.

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

Cependant, lorsque j'utilise cette configuration, j'obtiens une erreur lorsque j'essaie d'accéder à la base de données, indiquant qu'elle ne peut pas analyser la chaîne de connexion.

Je dois supposer que le problème provient de la manière dont la chaîne de connexion est spécifiée dans la variable d'environnement, mais après un certain temps de recherche en ligne, je n'ai pas été en mesure de trouver un exemple de ce à quoi la valeur de la variable d'environnement devrait ressembler. Par exemple, dois-je mettre des guillemets simples en début et en fin de chaîne autour de la chaîne? Les sections individuelles de la chaîne de connexion nécessitent-elles des guillemets simples ou doubles?

Toute aide, telle qu'un exemple de chaîne de connexion appropriée définie dans une variable d'environnement, serait grandement appréciée.

20
EiEiGuy

Une valeur de typo/mauvaise est définie dans vos variables de connexion.

Ce qui peut être vu dans cette sortie que vous avez collée:

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

Ceci est probablement arrivé lors de la définition de la variable via

$env:ConnectionStrings:MyDb = """Server=..."""

la méthode correcte consiste à le définir sans les guillemets.

$env:ConnectionStrings:MyDb = "Server=..."

Ancienne réponse (pour les autres utilisateurs susceptibles de rechercher des problèmes similaires)

La convention pour les chaînes de connexion est SQLCONNSTR_, MYSQLCONNSTR_, SQLAZURECONNSTR_ Et CUSTOMCONNSTR_, Qui sont utilisées par Azure Web Apps, mais devraient également fonctionner pour l'auto-hébergement. VM ou tout autre fournisseur de cloud.

Donc, si vous avez une variable d’environnement appelée CUSTOMCONNSTR_TestDb, Ce sera la même chose que de la définir dans appsettings.json dans

{
    "connectionStrings": {
        "TestDb": "..."
    }
}

Il remplacera également la valeur qu'il contient, si AddEnvironmentVariables() est appelée après .UseJsonFile(...). La dernière inscription gagne.

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    // This one needs to be last
    .AddEnvironmentVariables();

Vous pouvez également utiliser d'autres variables pour remplacer les valeurs de configuration. iirc. ASPNETCORE_ Est le préfixe par défaut (mais vous pouvez le changer dans la AddEnvironmentVariables("MY_")).

Ainsi, un ASPNETCORE_MySettings Remplace Configuration["MySettings"] (Ou Configuration.Get("MySettings")) et ASPNETCORE_My__Settings (Utilisez double trait de soulignement pour la hiérarchie des niveaux sous Linux, lisez où : est utilisé pour obtenir la configuration - Linux interdit les points-virgules dans les noms de variables) remplace Configuration["My:Settings"] de la même manière que

{
    "my": {
        "settings": "..."
    }
}

À moins qu'ils aient changé cela récemment.

FWIW: Les noms de variables d’environnement et de clés de configuration sont insensibles à la casse pour autant que je me souvienne.

19
Tseng

Dans votre configuration, vous avez cette ligne:

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

Cela indique à votre système de configuration qu'il peut exister un fichier JSON contenant des paramètres spécifiques à l'environnement. Donc, vous avez seulement besoin d’un fichier qui existe sur la boîte de production et qui s'appelle appSettings.Production.config contenant quelque chose comme ceci:

{
  "ConnectionStrings": {
     "TestDb": "Server=...;Catalog=...;Etc=..."
  }
}

Les valeurs ici remplaceront tout ce qui est spécifié dans le fichier de paramètres JSON de base.

0
DavidG