Более сложная аутентификация для панели мониторинга Hangfire

#asp.net #hangfire

Вопрос:

Я использую hangfire в приложении, и мне необходимо выполнить аутентификацию панели мониторинга с помощью моих репозиториев. Чтобы сделать это, я должен разрешить хранилище внутри метода авторизации Hangfire, но, используя OwinContext , я не смог этого сделать. Я решил использовать SimpleInjector для этого проекта, и, поскольку он регистрирует все во WebApiConfig Register время метода s, я хочу добраться до него. Недавно я использовал middleware as MessageHandler , и, исходя из этого, я успешно разрешил зависимость с помощью HttpRequestMessage . Но OwinContext я не могу добраться до него и устранить зависимость с его помощью HttpRequestMessage.GetDependencyScope() .

Вот как Hangfire предлагает выполнить аутентификацию для Asp.net приложения в их документации;

 public class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        // In case you need an OWIN context, use the next line, `OwinContext` class
        // is the part of the `Microsoft.Owin` package.
        var owinContext = new OwinContext(context.GetOwinEnvironment());

        // Allow all authenticated users to see the Dashboard (potentially dangerous).
        return owinContext.Authentication.User.Identity.IsAuthenticated;
    }
}
 

Поскольку я использую Angular на интерфейсе, это owinContext.Authentication.User значение равно нулю. И даже если бы это было не так, я хочу только сам дотянуться до приборной панели. Так что это не решило бы мою проблему.

Как я могу разрешить свои зависимости здесь внутри Authorize метода?

Я не могу сделать это с помощью инъекции конструктора, потому что для hangfire вы говорите UseHangfireDashboard на Startup.cs s Configuration , как указано ниже;

Это мое Startup.cs досье

 private IEnumerable<IDisposable> GetHangfireServers()
{
    Hangfire.GlobalConfiguration.Configuration
        .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
        .UseSimpleAssemblyNameTypeSerializer()
        .UseRecommendedSerializerSettings()
        .UseSqlServerStorage("CONN_STR", new SqlServerStorageOptions
        {
            CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
            SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
            QueuePollInterval = TimeSpan.Zero,
            UseRecommendedIsolationLevel = true,
            DisableGlobalLocks = true
        });

    yield return new BackgroundJobServer();
}

public void Configuration(IAppBuilder app)
{
    app.UseHangfireAspNet(GetHangfireServers);
    app.UseHangfireDashboard("/hangfire", new DashboardOptions { 
        Authorization = new [] { 
            new DashboardAuthorization() 
            /* explanation */ 
            // for DI to work through constructor, 
            //I have to give my AuthRepository as a parameter here. 
            //And my AuthRepository also has many DIs so, 
            //it's not possible through here.
        }
    });

    BackgroundJob.Enqueue(() => Console.WriteLine("Hello world from Hangfire!"));

}

 

Кстати, мой проект-это проект .Net Framework 4.7.2.

Комментарии:

1. Вы пробовали инъекцию конструктора? Сработало ли это? Каков был результат?

2. Нет, для того, чтобы сделать это, я должен отдать это от самого Startup.cs себя, и я, похоже, не в состоянии этого сделать.

3. Почему? Когда вы не в состоянии что-то сделать, пожалуйста, четко объясните, что вам мешает.

4. @mason Я отредактировал вопрос, чтобы показать, почему, спасибо за предложение 🙂

5. Вам не нужно складывать их в один файл. В файле Startup.cs создайте экземпляр контейнера DI и зарегистрируйте свои службы. Затем вы можете передать этот контейнер в конфигурацию веб-API, в конфигурацию Hangfire и в любое другое место, где он вам понадобится.

Ответ №1:

Что касается Hangfire, вы несете ответственность за предоставление экземпляра класса, реализующего IDashboardAuthorizationFilter. Поэтому, если у этого класса есть зависимости, которые вы хотите внедрить, это будет зависеть от вас. Вероятно, лучше всего зарегистрировать этот тип и его зависимости в вашем контейнере DI, и пусть он разрешит вам экземпляр. Таким образом, он позаботится о введении всех зависимостей для вас с помощью инъекции конструктора.

Вы должны в конечном итоге получить шаблон, подобный этому, в файле Startup.cs, где вы настраиваете конвейер OWIN.

 public void Configuration(IAppBuilder app)
{
    var container = CreateContainerWithRegisteredServices();
    var dashboardFilter = container.Resolve<IDashboardAuthorizationFilter>();

    app.UseHangfireDashboard("/hangfire", new DashboardOptions { 
        Authorization = new [] { dashboardFilter }
    });

    BackgroundJob.Enqueue(() => Console.WriteLine("Hello world from Hangfire!"));

    // Configure Web API, SignalR, or whatever else hangs off your OWIN pipeline.
    // You can pass the container into their configure methods if necessary.   
}

IContainer CreateContainerWithRegisteredServices()
{
    //this method will look different depending on your chosen IoC library
    var container = SomeIoCLibrary.CreateContainer();
    container.Register<MyAuthorizationFilter, IDashboardAuthorizationFilter>();
    //register other dependencies here

    return container;
}