当我尝试访问 localhost:5000/hangfire 时,我被重定向到错误页面(我有一个返回相对状态页面(400,404 等)的控制器)
我想 /hangfire 不存在。它所指的“HandeErrorCode”来自我的控制器。
[Route ("Error/{statusCode}")]
public IActionResult HandleErrorCode (int statusCode) {
var statusCodeData =
HttpContext.Features.Get<IStatusCodeReExecuteFeature> ();
switch (statusCode) {
case 404:
return View("Status404");
case 401:
return View("Status401");
case 400:
return View("Status400");
case 500:
return View("Status500");
}
return View ();
}
Run Code Online (Sandbox Code Playgroud)
启动.cs
配置服务
services.AddHangfire(configuration=>{
configuration.UsePostgreSqlStorage(connectionString);
});
Run Code Online (Sandbox Code Playgroud)
配置
app.UseHangfireDashboard("/hangfire");
app.UseHangfireServer();
Run Code Online (Sandbox Code Playgroud)
编辑:整个 Startup.cs
public class Startup {
public Startup (IHostingEnvironment env) {
Console.WriteLine ("startin app {0}, which uses env {1} and has root {2}", env.ApplicationName, env.EnvironmentName, env.ContentRootPath);
Configuration = new ConfigurationBuilder ()
.SetBasePath (env.ContentRootPath)
.AddJsonFile ("appsettings.json", optional : true, reloadOnChange : true)
.AddJsonFile ($"appsettings.{env.EnvironmentName}.json", optional : true)
.AddEnvironmentVariables ()
.Build ();
Console.WriteLine ("Current env variables are as follows: ");
var enumerator = Environment.GetEnvironmentVariables ().GetEnumerator ();
while (enumerator.MoveNext ()) {
Console.WriteLine ($"{enumerator.Key,5}:{enumerator.Value,100}");
}
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices (IServiceCollection services) {
services.AddMvc ();
// Add framework services.
var connectionString = Configuration["ConnectionStrings:DefaultConnection"];
Console.WriteLine ("using conn str: {0}", connectionString);
services.AddEntityFrameworkNpgsql ()
.AddDbContext<EntityContext> (
options => options.UseNpgsql (connectionString)
);
services.AddIdentity<User, Role> (config => {
config.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<EntityContext> ()
.AddDefaultTokenProviders ();
services.Configure<IdentityOptions> (options => {
options.Password.RequireDigit = false;
options.Password.RequiredLength = 5;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
});
services.ConfigureApplicationCookie (options => options.LoginPath = "/account/login");
services.AddAuthentication (CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie (options => {
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
});
// SERVICE FILTERS
services.AddScoped<ActivePackageFilterAttribute, ActivePackageFilterAttribute> ();
services.AddScoped<ActiveUserFilterAttribute, ActiveUserFilterAttribute> ();
services.AddSingleton<AccountBilling, AccountBilling> ();
services.AddMemoryCache ();
services.AddHangfire (configuration => {
configuration.UsePostgreSqlStorage (connectionString);
});
services.AddMvc (config => {
config.ModelBinderProviders.Insert (0, new InvariantDecimalModelBinderProvider ());
//config.Filters.Add(typeof(RedirectActionFilter));
})
.SetCompatibilityVersion (CompatibilityVersion.Version_2_2)
.AddJsonOptions (options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver ();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
})
.AddViewLocalization (LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
.AddDataAnnotationsLocalization ();
//services.AddScoped<RedirectActionFilter>();
services.AddAutoMapper ();
services.AddSingleton<AutoMapper.IConfigurationProvider> (Automapper.AutoMapperConfig.RegisterMappings ());
//services.AddSingleton(Mapper.Configuration);
services.AddScoped<IMapper> (sp => new Mapper (sp.GetRequiredService<AutoMapper.IConfigurationProvider> (), sp.GetService));
services.AddDistributedMemoryCache (); // Adds a default in-memory implementation of IDistributedCache
services.AddSession ();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender> ();
services.AddTransient<ISmsSender, AuthMessageSender> ();
services.AddScoped<IRepository, Repository> ();
services.AddScoped<Context, Context> ();
services.AddScoped<IAccountBilling, AccountBilling> ();
services.Configure<AdministratorEmailAddress> (Configuration);
services.Configure<AuthMessageSenderOptions> (Configuration);
services.Configure<TBCPaymentOptions> (Configuration);
services.AddScoped<ViewRender, ViewRender> ();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor> ();
services.Configure<RequestLocalizationOptions> (opts => {
var supportedCultures = new [] {
new CultureInfo ("en"),
new CultureInfo ("ka"),
new CultureInfo ("ru")
};
opts.DefaultRequestCulture = new RequestCulture ("ka");
// Formatting numbers, dates, etc.
opts.SupportedCultures = supportedCultures;
// UI strings that we have localized.
opts.SupportedUICultures = supportedCultures;
});
// Add converter to DI
//services.AddSingleton(typeof(IConverter), new BasicConverter(new PdfTools()));
services.AddSingleton<ITemplateService, TemplateService> ();
services.AddSingleton (typeof (IConverter), new SynchronizedConverter (new PdfTools ()));
services.AddScoped<MailComposer> ();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure (IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment ()) {
app.UseDeveloperExceptionPage ();
app.UseDatabaseErrorPage ();
} else {
app.UseStatusCodePagesWithReExecute ("/Error/{0}");
}
app.UseStaticFiles ();
app.UseAuthentication ();
app.UseForwardedHeaders (new ForwardedHeadersOptions {
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>> ();
app.UseRequestLocalization (options.Value);
app.UseSession ();
// app.UseHangfireDashboard ("/hangfire", new DashboardOptions {
// Authorization = new [] { new HangFireAuthorization () }
// });
app.UseHangfireDashboard ();
app.UseHangfireServer ();
RecurringJob.AddOrUpdate<IAccountBilling> (a => a.CheckUserPayment (), Cron.Minutely);
RecurringJob.AddOrUpdate<IAccountBilling> ("CalculateUserCharge", a => a.CalculateUserCharge (DateTime.Today.AddDays (-1)), Cron.Daily (21, 00), TimeZoneInfo.Utc);
//RecurringJob.AddOrUpdate<IAccountBilling>("CalculateUserCharge",a=>a.CalculateUserCharge(DateTime.Today.AddDays(-1)),Cron.Minutely);
app.UseMvc (routes => {
routes.MapRoute (
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Run Code Online (Sandbox Code Playgroud)
} }
HangfireAuthorization.cs
public class HangFireAuthorization: IDashboardAuthorizationFilter{
public bool Authorize([NotNull] DashboardContext context)
{
return context.GetHttpContext().User.IsInRole("Administrator");
}
Run Code Online (Sandbox Code Playgroud)
}
如何访问hangfire 仪表板?
对于Hangfire Dashboard,它公开了有关后台作业的敏感信息,包括方法名称和序列化参数,并让您有机会通过执行不同的操作 \xe2\x80\x93 重试、删除、触发等来管理它们。所以这非常重要限制对仪表板的访问。
为了确保默认情况下的安全,仅允许本地请求,但是您可以通过传递自己的 IDashboardAuthorizationFilter 接口实现来更改此设置,该接口的 Authorize 方法用于允许或禁止请求。第一步是提供您自己的实现。
\n参考配置授权
\n更新:
\n对于此行为,如上所述,并由HangfireApplicationBuilderExtensions控制。它注册LocalRequestsOnlyAuthorizationFilter。
\n如果要启用非本地主机的请求,则需要提供DashboardOptions.