ASP.NET MVC Core 2.0のアプリケーション全体でHTTPSを強制する
Created at:
ASP.NET MVC Core 2.0のアプリケーションでHTTPSを強制するには、RequireHttps
フィルター(RequireHttpsAttribute
クラス)をグローバルフィルターに追加することで実現できます。
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services
.AddMvc(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
}
注意点として、RequireHttpsAttribute
フィルターはOnAuthorization
メソッド、つまりフィルターパイプラインの一番最初である認可フェーズで処理されるので、ほかの認証/認可フィルターはこのフィルターより後に登録する必要があります。
MicrosoftのサイトにはRewriteエンジンを使う方法も書かれていますが、大抵のケースではフィルターで追加する方法で間に合うと思います。
MVCを使わないASP.NET Coreでもリダイレクトしたい
また、MVCではないASP.NET Coreで同じようなことをしたい場合には以下のようなMiddlewareを書くとよいでしょう(動作未確認)。
public static IApplicationBuilder UseRedirectToHttps(this IApplicationBuilder app)
{
return app.Use((context, next) =>
{
var req = context.Request;
if (!req.IsHttps)
{
var newUrl = new StringBuilder().Append("https://").Append(req.Host.Host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
context.Response.Redirect(newUrl.ToString(), permanent: true);
return Task.CompletedTask;
}
return next();
});
}
IHostingEnvironmentをConfigureServiceで使いたい
ところでグローバルなフィルターを追加するのはいいのですが、環境によっては例えばデバッグ実行時や開発環境では追加したくないということもあります。
Configure
メソッド内であれば env.IsProduction()
といった感じで切り替えできるのですが、ConfigureService
メソッドには IHostingEnvironment
が渡ってこないのです。
ではどうするかというと Startup
クラスにプロパティやフィールドをはやして、保持しておくという方法で解決できます。まあ Configuration
も保持してますしね。
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
HostingEnvironment = env;
}
public IHostingEnvironment HostingEnvironment { get; }
一度保持してしまえば ConfigureServices
から参照可能になるので環境ごとに切り替えができます。
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services
.AddMvc(options =>
{
if (HostingEnvironment.IsProduction())
{
options.Filters.Add(new RequireHttpsAttribute());
}
});
}