Как я могу заполнить поле UserId журнала аудита, если у меня нет доступа к HttpContext? - PullRequest
2 голосов
/ 19 сентября 2019

У меня есть решение с двумя проектами, моим уровнем API и моим уровнем данных.

Уровень данных использует Entity Framework и не знает о ASP.NET WebApi.

Уровень API использует ASP.NET WebApi.

Я планирую использовать Audit.NET для аудита изменений записей.

В настоящее время я установил Audit.NET, Audit.EntityFramework и Audit.WebApiв моем проекте API.

Я хочу использовать атрибут фильтра аудита.(config.Filters.Add(new AuditApiAttribute());)

Моя проблема заключается в том, что когда я заполняю объект EntityLog, я также хотел бы заполнить поле UserId идентификатором пользователя, выполняющего в настоящее время авторизованное действие, или нулевым, если действиеявляется анонимным.

Как часть моего Startup.cs, я запускаю эту функцию для настройки Audit.NET:

private void ConfigureAudit()
        {
            Audit.Core.Configuration.Setup()
                .UseEntityFramework(x => x
                    .AuditTypeMapper(t => typeof(AuditLog))
                    .AuditEntityAction<AuditLog>((ev, entry, entity) =>
                    {
                        entity.UserId = ???;
                        // other fields...
                    })
                    .IgnoreMatchedProperties()
                );
        }

Очевидно, что на данный момент я не могу использовать HttpContext.Current.User.Identity.GetUserId(), так как яне внутри контроллера, и я не вижу способа передачи UserId в событие Audit.

Как я могу получить UserId на этом этапе?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2019

В дополнение к ответу Стива, я думаю, вы сможете добавить Настраиваемое поле из OnScopeCreated настраиваемое действие , например, в логике запуска asp.net:

Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
    scope.SetCustomField("User", HttpContext.Current.User.Identity.GetUserId());
});

Таким образом, у вас будет это поле в AuditEvent вашего провайдера данных EF, и вы сможете получить его следующим образом:

Audit.Core.Configuration.Setup()
    .UseEntityFramework(_ => _
        .AuditTypeMapper(t => typeof(AuditLog))
        .AuditEntityAction<AuditLog>((ev, entry, entity) =>
        {
            var x = ev.CustomFields["User"];
            ...
        })
        .IgnoreMatchedProperties());

Примечание: если вас интересует тольков контексте контекста БД инфраструктуры сущностей вам не нужна библиотека Audit.WebApi.Это для проверки действий контроллера.

0 голосов
/ 19 сентября 2019

Подход, который я использую, - это интерфейс IUserContextLocator, который становится зависимостью от DbContext или любого другого класса, реализующего аудит.Реализация интерфейса создается в веб-приложении и подключается через внедрение зависимостей, чтобы использовать инициализацию конструктора для предоставления сведений о текущем сеансе.так что DbContext или другая служба аудита может разрешить текущую структуру пользователя из метода в IUserContextLocator, который, в свою очередь, выбирает из сеанса.

Моя текущая реализация работает, поэтому у меня нет удобного примера,но я могу добавить это завтра.Принцип, подобный этому, можно увидеть здесь: http://josephwoodward.co.uk/2014/06/sessions-asp-net-mvc-using-dependency-injection/

По существу, код уровня домена не будет иметь доступа к таким вещам, как HttpContext.Current, но реализация, инициализированная в вашем веб-приложении, может.Регистрируя эту реализацию в своем DI через общий интерфейс, на который может ссылаться ваш домен, вы можете внедрить зависимость, полученную из веб-приложения, что позволит вам получить доступ к данным сеанса.Этот пример называет это Registry, который может быть более точным шаблоном для него.

...