5 votes

Configuration d'ELMAH avec la journalisation SQL Server avec une chaîne de connexion chiffrée

Je tente de configurer la journalisation des erreurs ELMAH dans une application ASP.NET 4 en utilisant SQL Server 2008 R2. Existe-t-il un moyen de dire à ELMAH d'appeler notre fonction de décryptage interne sur la chaîne de connexion que nous lui fournissons ? Dois-je modifier la source ELMAH et la reconstruire ?

12voto

Atif Aziz Points 16967

Vous ne pouvez pas simplement dire à ELMAH quoi faire avec votre chaîne de connexion. Ce que vous pouvez faire, cependant, est dire à ELMAH de vous rappeler quand il a besoin d'un ErrorLog, vous donnant ainsi plus de contrôle à l'exécution. Vous pouvez ensuite lire la chaîne de connexion chiffrée, la décrypter avec votre fonction interne et retourner un SqlErrorLog initialisé avec celle-ci.

Pour ce faire, vous devez fournir une méthode compatible avec le ServiceProviderQueryHandler délégué. Voici la définition :

public delegate IServiceProvider ServiceProviderQueryHandler(object context); 

L'implémentation de la méthode doit retourner une instance d'un objet qui implémente IServiceProvider. Si vous ne voulez pas en écrire un vous-même pour commencer, vous pouvez en obtenir un gratuitement à partir du .NET Framework. Voir System.ComponentModel.Design.ServiceContainer. Le fournisseur de services GetService doit répondre aux demandes du type ErrorLog et vous pouvez alors, par exemple, retourner un objet SqlErrorLog initialisé avec une chaîne de connexion manipulée à l'exécution. Voici une implémentation possible :

var parent = ServiceCenter.Current;
ServiceCenter.Current = context => { 
    var container = new ServiceContainer(parent(context)); 
    var connectionSettings = ConfigurationManager.ConnectionStrings["FOOBAR"];
    var connectionString = Decrypt(connectionSettings.ConnectionString);
    var log = new SqlErrorLog(connectionString); 
    container.AddService(typeof(ErrorLog), log); 
    return container; 
  } ;

Cela capture le point de service actuel et installe le vôtre à la place. Le lambda/délégué créé transmet les demandes de service au point de service capturé lorsqu'il ne peut pas les satisfaire directement, créant ainsi une chaîne. Vous indiquez à ELMAH votre implémentation en définissant ServiceCenter.Current quelque part lors de l'initialisation de votre application, donc c'est là que le code ci-dessus devra se trouver.

Gardez à l'esprit que ceci est une implémentation très simple mais cela devrait être suffisant pour vous permettre de démarrer et d'optimiser ultérieurement si nécessaire.

Avant cet ajout dans la version 1.2, la seule façon de faire quelque chose de similaire nécessitait le sous-classement et d'autres gymnastiques et donnait encore des résultats partiels. Maintenant, vous avez juste besoin de mettre en œuvre une méthode et de la remettre à ELMAH qui répond simplement aux requêtes d'ELMAH pour des objets basés sur leur type de service.

3voto

Quandary Points 12867

En complément du post de Atif Aziz, voici la version VB.NET (InitializeElmah_VB9 pour la version .NET 2.0 [sans lambda], InitializeElmah pour VB.NET pour .NET 4.0)

Imports System.Web.SessionState

Public Class Global_asax
    Inherits System.Web.HttpApplication

    Public Overrides Sub Init()
        MyBase.Init()

        InitializeElmah_VB9()
        'InitializeElmah()'
    End Sub

    Public parent As Elmah.ServiceProviderQueryHandler = Nothing

    Sub InitializeElmah_VB9()
        ' TODO: Créer Tableau + Fonctions '
        parent = Elmah.ServiceCenter.Current
        Elmah.ServiceCenter.Current = AddressOf ElmahCallback
    End Sub

    Function ElmahCallback(objContext As Object) As System.IServiceProvider
        Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext))
        Dim connectionSettings As System.Configuration.ConnectionStringSettings = ConfigurationManager.ConnectionStrings("FOOBAR")

        Dim strConnectionString As String = connectionSettings.ConnectionString

        Dim x As New System.Data.SqlClient.SqlConnectionStringBuilder(strConnectionString)
        x.Password = CryptStrings.DeCrypt(x.Password)

        strConnectionString = x.ConnectionString

        Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(strConnectionString)
        container.AddService(GetType(Elmah.ErrorLog), log)
        Return container
    End Function

    Sub InitializeElmah()
        ' TODO: Créer Tableau + Fonctions '
        Dim parent As Elmah.ServiceProviderQueryHandler = Elmah.ServiceCenter.Current
        Elmah.ServiceCenter.Current = Function(context)
              Dim container As New System.ComponentModel.Design.ServiceContainer(parent(context))
              Dim connectionSettings As System.Configuration.ConnectionStringSettings = ConfigurationManager.ConnectionStrings("Foobar")
              Dim connectionString As String = connectionSettings.ConnectionString

              Dim x As New System.Data.SqlClient.SqlConnectionStringBuilder(connectionString)

              x.Password = CryptStrings.DeCrypt(x.Password)

              connectionString = x.ConnectionString

              Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(connectionString)
              container.AddService(GetType(Elmah.ErrorLog), log)

              Return container
          End Function

    End Sub

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché au démarrage de l'application '
    End Sub

    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché au démarrage de la session '
    End Sub

    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché au début de chaque demande '
    End Sub

    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché lors de la tentative d'authentification de l'utilisateur '
    End Sub

    Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché en cas d'erreur '
    End Sub

    Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché à la fin de la session '
    End Sub

    Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Déclenché à la fin de l'application '
    End Sub

End Class

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X