hangfire 是一個分佈式後臺執行服務。html
官網:http://hangfire.io/redis
我看中hangfire的地方是sql
1:使用簡單安全
2:多種持久化保存方案。支持sqlserver ,msmq等 ,其餘的redis 等持久化方案要收費。不過本身擴展不是難事。hangfire基於net3.5的extension擴展。app
3:有監控系統,而且能夠和其餘監控系統集成。 分佈式
回顧正題:ide
hangfire在部署到iis環境上,經過地址訪問的時候會出現401未受權錯誤。經過代碼分析是因爲hangfire內建受權機制形成的問題。sqlserver
在分析源碼前,建議先對owin作個瞭解:ui
http://www.cnblogs.com/dudu/p/what-is-owin.htmlurl
http://owin.org/
hangfire繼承了OwinMiddleware,在每次請求的時候會去執行IAuthorizationFilter的實現。
internal class DashboardMiddleware : OwinMiddleware { private readonly JobStorage _storage; private readonly RouteCollection _routes; private readonly IEnumerable<IAuthorizationFilter> _authorizationFilters; public override Task Invoke(IOwinContext context) { var dispatcher = _routes.FindDispatcher(context.Request.Path.Value); if (dispatcher == null) { return Next.Invoke(context); } foreach (var filter in _authorizationFilters) { if (!filter.Authorize(context.Environment)) { context.Response.StatusCode = (int) HttpStatusCode.Unauthorized; return Task.FromResult(false); } } var dispatcherContext = new RequestDispatcherContext( _storage, context.Environment, dispatcher.Item2); return dispatcher.Item1.Dispatch(dispatcherContext); } }
hangfire默認加載了 LocalRequestsOnlyAuthorizationFilter
public class LocalRequestsOnlyAuthorizationFilter : IAuthorizationFilter { public bool Authorize(IDictionary<string, object> owinEnvironment) { var context = new OwinContext(owinEnvironment); var remoteAddress = context.Request.RemoteIpAddress; // if unknown, assume not local if (String.IsNullOrEmpty(remoteAddress)) return false; // check if localhost if (remoteAddress == "127.0.0.1" || remoteAddress == "::1") return true; // compare with local address if (remoteAddress == context.Request.LocalIpAddress) return true; return false; } }
能夠看出來對remoteaddress作了限制。
若是不考慮安全的場合,能夠採用如下作法:
public class Startup { public void Configuration(IAppBuilder app) { app.UseHangfire(config => { config.UseAuthorizationFilters(new DontUseThisAuthorizationFilter()); config .UseSqlServerStorage(@"server=xxxxx;database=Hangfire;uid=sa;pwd=123.com") .UseMsmqQueues(@".\Private$\hangfire{0}", "default", "critical"); }); app.MapHangfireDashboard(); } }
public class DontUseThisAuthorizationFilter : IAuthorizationFilter { public bool Authorize(IDictionary<string, object> owinEnvironment) { return true; } }
若是須要結合現有系統權限機制的場合,也是實現IAuthorizationFilter:
GlobalContext.Current.UserInfo是咱們系統內部的一個上下文class。
public class CustomAuthorizationFilter : IAuthorizationFilter { public bool Authorize(IDictionary<string, object> owinEnvironment) { var context = new OwinContext(owinEnvironment); if ( GlobalContext.Current.UserInfo==null){ string urls = "/Index/Login?url=" + context.Request.Uri.Host; context.Response.Redirect(urls); return false; } return true; } }