アプリをApp Engineに公開したときに、HTTPからHTTPSへの自動リダイレクトが正しく機能しませんでした。
example.comを介してWebサイトにアクセスすると、サイトは http://www.example.com にルーティングされ、接続が保護されていないことが示されます。 https://www.example.com を介してWebサイトにアクセスすると、Googleが管理するSSLでWebサイトが正しく保護されます。ただし、HTTPからHTTPSへの自動リダイレクトは行われません。
ログビューアで、Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddlewareがスローされ、リダイレクト用のhttpsポートを特定できなかったことを警告するエラーも発生しました。
私はMSDNのドキュメントに従って、ローカルでのみ機能するようにしましたが、アプリがApp Engineに公開されたときは機能しません。 https://docs.Microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&tabs=visual-studio
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory logger)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseStatusCodePages();
app.UseExceptionHandler("/Error");
app.UseHsts(); // This was added by the template
}
app.UseHttpsRedirection(); // This was added by the template
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc();
}
これがProgram.csです。基本的にプロジェクトテンプレートからのデフォルト
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
.UseStartup<Startup>();
}
デプロイに使用されるapp.yaml
runtime: aspnetcore
env: flexible
automatic_scaling:
min_num_instances: 1
max_num_instances: 20
cpu_utilization:
target_utilization: 0.8
readiness_check:
path: "/readinesscheck"
check_interval_sec: 5
timeout_sec: 4
failure_threshold: 2
success_threshold: 2
app_start_timeout_sec: 300
liveness_check:
path: "/livenesscheck"
check_interval_sec: 30
timeout_sec: 4
failure_threshold: 2
success_threshold: 2
skip_files:
- node_modules/
- wwwroot/src/vendor/
- ^(.*/)?.*\.pdb$
- ^(.*/)?.*\.log$
その結果、アプリにアクセスできなくなりました(502サーバーエラー)。
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
options.HttpsPort = 443;
});
また、アプリにアクセスできなくなった(502サーバーエラー)。
env_variables:
ASPNETCORE_HTTPS_PORT: "443"
また、アプリにアクセスできなくなった(502サーバーエラー)。
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080") // also return 502 when port is 443
アプリはアクセス可能ですが、自動HTTP/HTTPSリダイレクトはありません。
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
app.UseForwardedHeaders();
アプリはアクセス可能ですが、自動HTTP/HTTPSリダイレクトはありません。 app.yamlのランタイムがaspnetcoreに設定されていることを理解しています。公開プロセスは、アプリをApp Engineにデプロイするために使用される独自のDockerfileを自動的に生成しました。
EXPOSE 443
EXPOSE 8080
どういうわけか、 Microsoft および App Engine のドキュメントのこのヒントに従って、「X-Forwarded-Proto」ヘッダーを探す独自のミドルウェアを作成した後、これを機能させました。
Microsoft:アプリがUseForwardedHeadersで転送ヘッダーを処理するには、転送ヘッダーミドルウェアを有効にする必要があります。
App Engine:SSL接続はロードバランサで終了します。ロードバランサーからのトラフィックは、暗号化されたチャネルを介してインスタンスに送信され、HTTPを介してアプリケーションサーバーに転送されます。 X-Forwarded-Protoヘッダーを使用すると、OriginリクエストがHTTPであるか、HTTPsであるかを理解できます。
Microsoftは、アプリが転送されたヘッダーの処理を開始する前に、まずミドルウェアをアクティブ化する必要があります
ConfigureServicesメソッドでミドルウェアオプションを設定します
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
そしてそれをConfigureメソッドの中で何よりも先に使用します
app.UseForwardedHeaders();
次に、転送されたヘッダーを読み取り、クエリを含むHTTPSにリダイレクトするカスタムミドルウェアを作成します。
Configureメソッド内
app.Use(async (context, next) =>
{
if (context.Request.IsHttps || context.Request.Headers["X-Forwarded-Proto"] == Uri.UriSchemeHttps)
{
await next();
}
else
{
string queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : string.Empty;
var https = "https://" + context.Request.Host + context.Request.Path + queryString;
context.Response.Redirect(https);
}
});
最後に、Configureメソッドは次のようになります
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseForwardedHeaders();
app.Use(async (context, next) =>
{
if (context.Request.IsHttps || context.Request.Headers["X-Forwarded-Proto"] == Uri.UriSchemeHttps)
{
await next();
}
else
{
string queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : string.Empty;
var https = "https://" + context.Request.Host + context.Request.Path + queryString;
context.Response.Redirect(https);
}
});
if (env.IsDevelopment())
{
// code removed for clarity
}
else
{
// code removed for clarity
app.UseHsts();
}
app.UseHttpsRedirection();
// code removed for clarity
app.UseMvc();
}
example.com に移動して、直接リダイレクトする https://www.example.com
スキームは、任意のタイプのミドルウェアを使用する前に、Startup.Configure
で手動で設定できます。
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});