【问题标题】:ASP.NET Core MVC Hangfire custom authenticationASP.NET Core MVC Hangfire 自定义身份验证
【发布时间】:2017-01-12 21:46:46
【问题描述】:

我设法在我的 ASP.NET Core MVC 应用程序上使用 Hangfire,现在我正在尝试添加管理员授权。

我在 Startup.cs 文件中添加了以下代码:

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

app.UseHangfireServer();
RecurringJob.AddOrUpdate( () => Debug.WriteLine("Minutely Job"), Cron.Minutely);

现在我遇到了自定义授权过滤器的问题:

public class HangFireAuthorizationFilter : IDashboardAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        return true;
    }
}

有IAutohorizationFilter的旧配置示例,1.6.8版本有一个新接口IDashboardAuthorizationFilter,我不知道如何实现。

我的网络应用程序使用声明。

thnx

【问题讨论】:

  • 你用的是哪个版本的hangfire?

标签: c# asp.net-core-mvc hangfire


【解决方案1】:

在hangfire中为asp.net core添加自定义基本身份验证

使用 Hangfire.Dashboard.Basic.Authentication nuget 包。

使用命令安装

Install-Package Hangfire.Dashboard.Basic.Authentication

Reference

在启动配置方法中添加以下内容

app.UseHangfireDashboard("/hangfire", new DashboardOptions
        {
            //AppPath = "" //The path for the Back To Site link. Set to null in order to hide the Back To  Site link.
            DashboardTitle = "My Website",
            Authorization = new[]
        {
                new HangfireCustomBasicAuthenticationFilter{
                    User = _configuration.GetSection("HangfireSettings:UserName").Value,
                    Pass = _configuration.GetSection("HangfireSettings:Password").Value
                }
            }
        });

在 appsettings.json 中添加以下内容(使用您的用户名和密码)

 "HangfireSettings": {
     "UserName": "admin",
     "Password": "password"
 }

【讨论】:

  • 谢谢你最简单的。
  • 这应该是公认的答案,适用于 .net core 3.1、sqlite 存储和内存存储
  • "IDX12741: JWT: 'System.String' 必须具有三个段 (JWS) 或五个段 (JWE)。" @ArsmanAhmad
  • 是的@RasoolAghajani。谢谢
  • 输入此代码 我在浏览器中收到此错误:“IDX12741: JWT: 'System.String' 必须有三个段 (JWS) 或五个段 (JWE)。”你知道这是什么吗? @ArsmanAhmad
【解决方案2】:

这是我的 .NET Core 实现:

public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter {
    private string policyName;

    public HangfireAuthorizationFilter(string policyName) {
        this.policyName = policyName;
    }

    public bool Authorize([NotNull] DashboardContext context) {
        var httpContext = context.GetHttpContext();
        var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
        return authService.AuthorizeAsync(httpContext.User, this.policyName).ConfigureAwait(false).GetAwaiter().GetResult().Succeeded;
    }
}

在Startup Configure 中设置它:

app.UseHangfireDashboard(
            pathMatch: "/hangfire",
            options: new DashboardOptions() {
                Authorization = new IDashboardAuthorizationFilter[] {
                    new HangfireAuthorizationFilter("somePolicy")
                }
            });

确保您选择的策略(例如“somePolicy”)之前已在 Startup ConfigureServices 中设置。例如:

services.Configure<AuthorizationOptions>(options => {
    options.AddPolicy("somePolicy", policy => {
        // require the user to be authenticated
        policy.RequireAuthenticatedUser();
        // Maybe require a claim here, if you need that.
        //policy.RequireClaim(ClaimTypes.Role, "some role claim");
    });
});

【讨论】:

  • @FarajFarook 你能详细说明一下吗?我在 .NET Core 1.0.1 上工作,有可能在 1.1 上发生了一些变化。
  • 该死的人。我的错。我忘了using Microsoft.Extensions.DependencyInjection; 我会检查整个解决方案,如果可行,请给你一个大拇指。很抱歉给我带来了困惑。
  • 由于某种原因,我的仪表板上下文未经过身份验证。我使用 UserManager 通过 AccountController 登录。
  • 我可能应该在我的回答中更清楚地说明这一点,但是您是否确保您提供给HangfireAuthorizationFilter 的策略(在本例中为“somePolicy”)是您已经使用的有效策略设置?我会更新我的答案。
  • 与github.com/blowdart/AspNetAuthorizationWorkshop 角色授权示例配合得很好
【解决方案3】:

如果您使用的是 .NET Core 2.0,则需要自定义实现以符合新的身份验证标准。

您需要添加一个中间件。 这个是 HangFire 在他们的 Github 页面/问题中提供的。

public class HangfireDashboardMiddleware
{
    private readonly DashboardOptions _dashboardOptions;
    private readonly JobStorage _jobStorage;
    private readonly RequestDelegate _nextRequestDelegate;
    private readonly RouteCollection _routeCollection;

    public HangfireDashboardMiddleware(
        RequestDelegate nextRequestDelegate,
        JobStorage storage,
        DashboardOptions options,
        RouteCollection routes)
    {
        _nextRequestDelegate = nextRequestDelegate;
        _jobStorage = storage;
        _dashboardOptions = options;
        _routeCollection = routes;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        var aspNetCoreDashboardContext =
            new AspNetCoreDashboardContext(_jobStorage, _dashboardOptions, httpContext);

        var findResult = _routeCollection.FindDispatcher(httpContext.Request.Path.Value);
        if (findResult == null)
        {
            await _nextRequestDelegate.Invoke(httpContext);
            return;
        }

        // attempt to authenticate against default auth scheme (this will attempt to authenticate using data in request, but doesn't send challenge)
        var result = await httpContext.AuthenticateAsync();

        if (!httpContext.User.Identity.IsAuthenticated)
        {
            // request was not authenticated, send challenge and do not continue processing this request
            await httpContext.ChallengeAsync();
        }

        if (_dashboardOptions
            .Authorization
            .Any(filter =>
                     filter.Authorize(aspNetCoreDashboardContext) == false))
        {
            var isAuthenticated = httpContext.User?.Identity?.IsAuthenticated;
            httpContext.Response.StatusCode = isAuthenticated == true
                                                  ? (int) HttpStatusCode.Forbidden
                                                  : (int) HttpStatusCode.Unauthorized;
            return;
        }

        aspNetCoreDashboardContext.UriMatch = findResult.Item2;
        await findResult.Item1.Dispatch(aspNetCoreDashboardContext);
    }
}

然后在你的 Startup.cs 你需要添加这个方法

private static IApplicationBuilder UseHangfireDashboardCustom(IApplicationBuilder app,string pathMatch = "/hangfire",DashboardOptions options = null,JobStorage storage = null)
{
    var services = app.ApplicationServices;
    storage = storage ?? services.GetRequiredService<JobStorage>();
    options = options ?? services.GetService<DashboardOptions>() ?? new DashboardOptions();
    var routes = app.ApplicationServices.GetRequiredService<RouteCollection>();

    app.Map(new PathString(pathMatch), x =>
        x.UseMiddleware<HangfireDashboardMiddleware>(storage, options, routes));

    return app;
}

最后,使用自定义授权

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseAuthentication();

        app.UseMvc(routes => routes.MapRoute(
                       "default",
                       "{controller=Home}/{action=Index}/{id?}"));

        app.UseHangfireServer();

        //Voila!
        UseHangfireDashboardCustom(app);
    }

【讨论】:

    【解决方案4】:

    这就是我实现IDashboardAuthorizationFilter的方式

    public class HangfireAuthorizeFilter : IDashboardAuthorizationFilter
    {
        public bool Authorize(DashboardContext context)
        {
            var owinEnvironment = context.GetOwinEnvironment();
            if (owinEnvironment.ContainsKey("server.User"))
            {
                if (owinEnvironment["server.User"] is ClaimsPrincipal)
                {
                    return (owinEnvironment["server.User"] as ClaimsPrincipal).Identity.IsAuthenticated;
                }
                else if (owinEnvironment["server.User"] is GenericPrincipal)
                {
                    return (owinEnvironment["server.User"] as GenericPrincipal).Identity.IsAuthenticated;
                }
            }
            return false;
        }
    }
    

    在你的创业公司

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

    【讨论】:

    • Kim Hoang,当我尝试这个时,它说 Exception throw: 'System.ArgumentException' in Hangfire.Core.dll 附加信息:上下文参数应该是 OwinDashboardContext!
    • @Wasyster,这很奇怪,实际上我为 MVC 5 实现了该属性。但它应该与 MVC 核心相同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2018-02-24
    • 2013-09-06
    • 1970-01-01
    • 2016-07-05
    相关资源
    最近更新 更多