Foreword
CreateWebHostBuilder and ASP.Net Core2.X main difference is that the call to the call 3.X of WebHost, CreateDefaultBuilder is replaced Host, another difference is a call to ConfigureWebHostDefaults () a;
Since the new host Builder is a generic host generator, so we also need to know the default Web Host Configuration what the default configuration. ConfigureWebHostDefaults
What had been the default configuration for us? We take a look at his default configuration for our HostFiltering , HostFilteringMiddleware , in fact, he has done is to limit the request to the host header, also equivalent to a white list host header request, identify the host header you can access some of the rest of you do not visit me here is not allowed.
how to use
In the beginning this is intended to share with you how to configure; Well, we explore together to see how he was thinking about doing it this way say that middleware ASP.NET Core How we use when we use. configuration, using the host header whitelist
services.PostConfigure<HostFilteringOptions>(options =>
{
if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
{
// "AllowedHosts": "localhost;127.0.0.1;[::1]"
var hosts = Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
// Fall back to "*" to disable.
options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
}
});
HostFilteringOptions
- AllowedHosts allow access Host Host
- Host request header AllowEmptyHosts whether to allow access to the default null value is true
- IncludeFailureMessage returns an error message, the default is true
Add HostFiltering middleware Configure method
public void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHostFiltering();
app.Run(context =>
{
return context.Response.WriteAsync("Hello World! " + context.Request.Host);
});
}
appsettings.json
{
"AllowedHosts": "127.0.0.1"
}
That's all, so let's test it and see.
Source resolve
/// <summary>
/// Processes requests
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public Task Invoke(HttpContext context)
{
var allowedHosts = EnsureConfigured();//获取允许Host集合
if (!CheckHost(context, allowedHosts))//判断当前Host是否在允许的Host集合中
{
return HostValidationFailed(context);//如果不在400
}
return _next(context);//继续走下一个中间件
}
private Task HostValidationFailed(HttpContext context)
{
context.Response.StatusCode = 400;
if (_options.IncludeFailureMessage)
{
context.Response.ContentLength = DefaultResponse.Length;
context.Response.ContentType = "text/html";
return context.Response.Body.WriteAsync(DefaultResponse, 0, DefaultResponse.Length);
}
return Task.CompletedTask;
}
private IList<StringSegment> EnsureConfigured()
{
if (_allowAnyNonEmptyHost == true || _allowedHosts?.Count > 0)//判断配置是否为空
{
return _allowedHosts;
}
return Configure();
}
private IList<StringSegment> Configure()
{
var allowedHosts = new List<StringSegment>();
if (_options.AllowedHosts?.Count > 0 && !TryProcessHosts(_options.AllowedHosts, allowedHosts))
{
_logger.WildcardDetected();
_allowedHosts = allowedHosts;
_allowAnyNonEmptyHost = true;
return _allowedHosts;
}
if (allowedHosts.Count == 0)//至少一个Host
{
throw new InvalidOperationException("No allowed hosts were configured.");
}
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.AllowedHosts(string.Join("; ", allowedHosts));
}
_allowedHosts = allowedHosts;
return _allowedHosts;
}
to sum up
This article may give you open it thinking, in fact, achieved his logic is simple, when we took Host request header to access through the middleware determines whether the Host header in our pre-configured inside, if inside then continue to request the next middleware, if say so embarrassed at 400