web-dev-qa-db-ja.com

ASP.NET Core 2.1 App EngineでのHTTP / HTTPSリダイレクトなし

問題

アプリをApp Engineに公開したときに、HTTPからHTTPSへの自動リダイレクトが正しく機能しませんでした。

example.comを介してWebサイトにアクセスすると、サイトは http://www.example.com にルーティングされ、接続が保護されていないことが示されます。 https://www.example.com を介してWebサイトにアクセスすると、Googleが管理するSSLでWebサイトが正しく保護されます。ただし、HTTPからHTTPSへの自動リダイレクトは行われません。

Insecured connection

ログビューアで、Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddlewareがスローされ、リダイレクト用のhttpsポートを特定できなかったことを警告するエラーも発生しました。

enter image description here

私は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$

私が試したことは次のとおりです(一度に1つだけ)

  1. AddHttpsRedirectionミドルウェアをConfigureServicesメソッドに追加します。

その結果、アプリにアクセスできなくなりました(502サーバーエラー)。

services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
    options.HttpsPort = 443;
});
  1. EnvironmentVariableをapp.yamlに追加します

また、アプリにアクセスできなくなった(502サーバーエラー)。

env_variables:
   ASPNETCORE_HTTPS_PORT: "443"
  1. Program.csでHTTPSポートを手動で構成する

また、アプリにアクセスできなくなった(502サーバーエラー)。

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080") // also return 502 when port is 443
  1. ConfigureServicesメソッドでForwardedHeaderOptionsを構成し、ConfigureメソッドでForwardedHeaderOptionsを使用します。 https://docs.Microsoft.com/en-us/aspnet/core/Host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1#other-proxy-server-and-load-バランサーシナリオ

アプリはアクセス可能ですが、自動HTTP/HTTPSリダイレクトはありません。

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = 
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

app.UseForwardedHeaders();
  1. Dockerfileでポート443および8080を手動で公開します。

アプリはアクセス可能ですが、自動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();
});
0
A. Morel