Аутентификация NetCore в веб-ферме (PCF) - PullRequest
0 голосов
/ 21 марта 2019

У меня есть приложение NetCore 2.1 API, обслуживающее внешний интерфейс Angular 5 UI.Оба приложения развернуты в Pivotal Cloud Foundry (pcf).

Аутентификация осуществляется с помощью аутентификации cookie без идентификатора

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {                   
                options.Cookie.Name = MyCookie;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                options.Cookie.Expiration = TimeSpan.FromMinutes(30);
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = 401;
                    ErrorHandlerUtility.HandleUnauthorizedError(context.HttpContext);
                    return Task.CompletedTask;
                };
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = 403;
                    ErrorHandlerUtility.HandleUnauthorizedError(context.HttpContext);
                    return Task.CompletedTask;
                };
            });`

И затем при входе в систему:

        var principal = CreateClaimsPrincipal(claims);         
        context.User = principal;
        Thread.CurrentPrincipal = principal;

        await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

И при выходе из системы:

  if (Request?.Cookies != null)
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        }

Все работало нормально, пока я не масштабировал экземпляр pcf (с 1 до 2)

Кажется, я не могу вызывать контроллеры с помощьюаутентифицированные пользователи больше (я перенаправлен на Unauthorized) при запуске более 1 экземпляра.

//[Authorize(Policy = PolicyOwnerRequired)]
[Authorize]
public class SomeController : Controller

Я рассмотрел возможность кэширования пользователя в сеансе redis, сеанс аутентификации (ITicketStore) на основе Cookie Authentication Early Expiration

Изучил DataProtection на основе DataProtection с redis

, но, похоже, ничего не работает.Я делаю это неправильно?Есть ли какой-то встроенный способ работы с несколькими экземплярами HttpContext, работающими в веб-ферме?или я должен искать какую-то пользовательскую аутентификацию, где я просто читаю куки из заголовков запросов?

Спасибо

ОБНОВЛЕНИЕ !!!

Я использовал пакет SteelToe для сохранения ключей для перенаправления.

services.AddDataProtection()
        .PersistKeysToRedis(redis, "DataProtection-Keys")
        .SetApplicationName("my_auth");

Я обновился до Microsoft.AspNetCore.DataProtection.StackExchangeRedis

И, похоже, работает.Может ли кто-нибудь убедиться, что я все делаю правильно?Цель состоит в том, чтобы несколько пользователей могли входить и выходить из системы без вмешательства нескольких браузеров в нескольких экземплярах

var redisConnection = ConnectionMultiplexer.Connect(RedisUtility.GetRedisConfigurations());
        var protectionProvider = CreateRedisProvider(redisConnection);

        // Data protection keys to persist in redis for authentication
        services.AddDataProtection().PersistKeysToStackExchangeRedis(redisConnection, "DataProtection-Keys")
            .SetApplicationName(applicationName);

        // Configure Cookie authentication
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.DataProtectionProvider = protectionProvider;
                options.Cookie.Name = cookieName;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                options.Cookie.Expiration = TimeSpan.FromMinutes(30);
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = 401;
                    ErrorHandlerUtility.HandleUnauthorizedError(context.HttpContext);
                    return Task.CompletedTask;
                };
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = 403;
                    ErrorHandlerUtility.HandleUnauthorizedError(context.HttpContext);
                    return Task.CompletedTask;
                };
            });

private static IDataProtectionProvider CreateRedisProvider(IConnectionMultiplexer connection)
    {
        return new ServiceCollection()
            .AddDataProtection()
            .PersistKeysToStackExchangeRedis(connection)
            .Services
            .BuildServiceProvider()
            .GetRequiredService<IDataProtectionProvider>();
    }
...