У меня есть приложение 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>();
}