ASP.NET Core 2.0, Kubernetes, https отсутствует в ответном адресе?

У меня есть веб-приложение ASP.NET Core 2.0, развернутое в кластере Kubernetes. Приложение использует Azure AD для аутентификации на некоторых защищенных страницах. Кластер Kubernetes настроен с использованием контроллера входящего трафика Nginx и Let's encrypt для поддержки https.

Я могу получить доступ к https://x.eastus.cloudapp.azure.com без проблем, и, щелкнув ссылку на сайте, я перенаправляюсь на https://x.eastus.cloudapp.azure.com/link, также без проблем.

Но когда я нажимаю на ссылку, для которой требуется авторизованный пользователь, я получаю:

Sign in
Sorry, but we’re having trouble signing you in.

AADSTS50011: The reply address 'http://x.eastus.cloudapp.azure.com/signin-oidc' does not match the reply addresses configured for the application: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx'. More details: not specified

Обратите внимание, что в приведенном выше URL отсутствует https, и это проблема.

Я зарегистрировал «https://x.eastus.cloudapp.azure.com/signin-oidc» в качестве URL-адреса ответа для приложения в Azure AD.

Но я не понимаю, почему в URL-адресе ответа, используемом при входе в систему, отсутствует https.

Если я разверну такое же приложение в веб-приложении Azure, у меня не будет этой проблемы.

В чем может быть проблема?

Это мой файл Ingress YAML:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: x-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    # Add to generate certificates for this ingress
    kubernetes.io/tls-acme: 'true'
spec:
  rules:
    - host: x.eastus.cloudapp.azure.com
      http:
        paths:
          - path: /
            backend:
              serviceName: x-service
              servicePort: 80
  tls:
    # With this configuration kube-lego will generate a secret called `x-tls-secret`
    # for the URL `x.eastus.cloudapp.azure.com`
    - hosts:
        - "x.eastus.cloudapp.azure.com"
      secretName: x-tls-secret

В Startup.cs есть следующий код:

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

    services.Configure<MvcOptions>(options =>
    {
        options.Filters.Add(new RequireHttpsAttribute());
    });

    services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddAzureAd(options => Configuration.Bind("AzureAd", options))
    .AddCookie();

    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseForwardedHeaders();

    app.UseStaticFiles();

    app.UseAuthentication();
}

Вам нужны экспедиторы. docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…

Tratcher 14.04.2018 01:43

@Tratcher У вас есть дополнительная информация о настройке серверов пересылки для этого сценария? Я добавил часть кода, упомянутого в статье, на которую вы ссылаетесь, и отредактировал свое исходное сообщение, чтобы включить этот код. Но я все равно получаю ту же ошибку.

OlavT 16.04.2018 15:43
docs.microsoft.com/en-us/aspnet/core/host-and-deploy/… рассказывает об установке заголовков x-forwarded- * для nginx. Не показывать, как это соотносится с кубернетами.
Tratcher 16.04.2018 17:10

Это в значительной степени то, что я сделал, и я использую Nginx с Kubernetes.

OlavT 16.04.2018 18:53
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
2
4
880
2

Ответы 2

Добавьте настраиваемое ПО промежуточного слоя в методе Configure для выполнения перенаправления http-https вручную.

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);
    }
});

Я знаю, что это старый, но у меня была аналогичная проблема с ASP .NET Core 3 и библиотекой IdentityModel с настраиваемым поставщиком OpenID Connect. URL-адреса перенаправления также будут http вместо https.

Мне пришлось сделать несколько вещей, чтобы наконец заставить его работать:

  • настроить прямые заголовки, чтобы сообщить ASP .NET Core использовать заголовки x-forwared-for и x-forwarded-proto, которые отправляет входящий поток.
  • указать ASP .NET Core доверять прокси из сетей Kubernetes
  • повысить предел пересылки, который сообщает ASP .NET Core, сколько переадресации может произойти

Вот соответствующий код запуска (обязательно измените диапазоны IP-адресов в соответствии с вашим кластером:

  public void ConfigureServices(IServiceCollection services)
  {
    services.Configure<ForwardedHeadersOptions>(options =>
    {
      // This tells the middleware to update IP and scheme according to forwarded headers
      options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
      options.ForwardLimit = 2;

      // Add Kubernetes Networks to trusted networks
      options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.42.0.0"), 16));
      options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("the IP range of our cluster nodes"), 27));
    });

    // ...
  }

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
  {
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
    }
    else
    {
      app.UseExceptionHandler("/Error");

      // Enable to process forward headers from https proxy like ingress nginx, this middleware must run before others
      // configuration is above in ConfigureServices
      app.UseForwardedHeaders();
    }

    // ...
  }

Как ни странно, это срабатывало только иногда. Иногда он все равно пытался перенаправить на HTTP-страницу, и после повторного развертывания он внезапно работал. Так что я также добавил app.UseHttpsRedirection(); к методу Configure, и, наконец, кажется, что он каждый раз работает.

Обновлено: немного ниже в этот блог объясняется, почему вам нужно установить ForwardLimit как минимум на 2.

Другие вопросы по теме