Настройка ELMAH с ведением журнала SQL Server с зашифрованной строкой соединения - PullRequest
5 голосов
/ 12 мая 2011

Я пытаюсь настроить ведение журнала ошибок ELMAH в приложении ASP.NET 4 с использованием SQL Server 2008 R2. Можно ли как-то сказать ELMAH вызвать нашу внутреннюю функцию дешифрования в строке подключения, которую мы предоставляем? Нужно ли изменять исходный код ELMAH и перестраивать?

<configSections>
  <sectionGroup name="elmah">
    <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
    <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
  </sectionGroup>
</configSections>

<elmah>
  <security allowRemoteAccess="1" />
  <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" />
</elmah>

<connectionStrings>
  <add name="ELMAH" connectionString="EncryptedConnectionString" providerName="System.Data.SqlClient" />
</connectionStrings>

<system.webServer>
  <handlers>
    <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
  </handlers>
  <modules>
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
  </modules>
</system.webServer>

Ответы [ 2 ]

12 голосов
/ 13 мая 2011

Вы не можете просто сказать ELMAH что-то сделать с вашей строкой соединения.Однако вы можете попросить ELMAH перезвонить вам, когда ему понадобится ErrorLog, что даст вам больше контроля во время выполнения.Затем вы можете прочитать зашифрованную строку подключения, расшифровать ее с помощью собственной функции и вернуть инициализированный с ней SqlErrorLog.

Для этого вам необходимо предоставить метод, совместимый с ServiceProviderQueryHandler делегат.Вот определение:

public delegate IServiceProvider ServiceProviderQueryHandler(object context); 

Реализация метода должна возвращать экземпляр объекта, который реализует IServiceProvider.Если вы не хотите писать самостоятельно, вы можете получить его бесплатно в .NET Framework.См. System.ComponentModel.Design.ServiceContainer.GetService поставщика услуг должен отвечать на запросы для типа ErrorLog, и вы можете, например, вернуть объект SqlErrorLog, который был инициализирован с помощью строки подключения, которой манипулируют во время выполнения.Вот возможная реализация:

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

Это захватывает текущую точку обслуживания и устанавливает вместо нее вашу собственную.Когда лямбда / делегат передает запросы на обслуживание захваченной точке обслуживания, когда она не может удовлетворить ее напрямую, создается цепочка.Вы рассказываете ELMAH о своей реализации, устанавливая ServiceCenter.Current где-то во время инициализации вашего приложения, так что именно там должен находиться приведенный выше код.

Помните, что это очень простая реализация, но она должна быть хорошейДостаточно, чтобы начать и оптимизировать позже, если это необходимо.

До этого добавления в 1.2 , единственный способ сделать что-то подобное требовал подклассов и другой гимнастики и все еще давал частичные результаты.Теперь вам просто нужно реализовать метод и передать его ELMAH, который просто отвечает на запросы ELMAH для объектов на основе их типа обслуживания.

3 голосов
/ 15 ноября 2011

В качестве дополнения к посту Atif Aziz, здесь версия VB.NET (InitializeElmah_VB9 для версии .NET 2.0 [без lamdda], InitializeElmah для VB.NET для .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: Create Table + Functions '
        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: Create Table + Functions '
        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)
        ' Wird beim Starten der Anwendung ausgelöst
    End Sub


    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird beim Starten der Sitzung ausgelöst
    End Sub


    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird zu Beginn jeder Anforderung ausgelöst
    End Sub


    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird beim Versuch der Benutzerauthentifizierung ausgelöst
    End Sub


    Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird bei einem Fehler ausgelöst
    End Sub


    Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird beim Beenden der Sitzung ausgelöst
    End Sub


    Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
        ' Wird beim Beenden der Anwendung ausgelöst
    End Sub


End Class
...