Вопрос или проблема
Я использую ASP.net core 8 (планирую обновить до 9, когда он будет выпущен).
У меня есть 2 веб-сайта: первый доступен внутри корпоративной сети, использует аутентификацию Windows.
Вторая копия того же сайта находится на внешнем веб-сервере и использует аутентификацию по кукам.
Одна из ключевых проблем заключается в том, что когда веб-сайт обновляется, мне нужно публиковать код в двух местах (один и тот же код, просто разные файлы AppSettings.Production.json).
Что я пытаюсь достичь, так это вместо того, чтобы иметь 2 копии одного и того же веб-сайта с разными схемами аутентификации, иметь только 1 копию, использующую куки, но с другим веб-сайтом, который использует аутентификацию Windows и автоматически создает куки для основного сайта на основе текущего пользователя.
Это позволяет пользователю войти в систему, используя куки, установленные через стандартную страницу входа (внешняя сеть) или через другой веб-сайт с аутентификацией Windows (внутренний доступ).
Чтобы попытаться реализовать это, я создал тестовое решение, содержащее 2 веб-сайта:
- Asp.Net Core (MVC) с аутентификацией Windows
- Asp.net Razor page (использует опцию аутентификации отдельных учетных записей)
На сайте с аутентификацией Windows я добавил следующий код в Program.cs
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddCookie("CookieAuthenticationScheme") // Новое ************
.AddNegotiate();
и
builder.Services.AddDataProtection() // Новое (добавлено перед var app = builder.Build())
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\KeyLocation"))
.SetApplicationName("SharedCookieApp");
builder.Services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
});
Затем в Home/Index я добавил
public class HomeController : Controller
{
public async Task<IActionResult> Index()
{
var c = HttpContext;
var userName = c.User.Identity?.Name;
if (userName != null)
{
userName = "[email protected]"; // Имя соответствует пользователю, созданному в asp.net identity на другом сайте
IEnumerable<Claim> claims = [new(ClaimTypes.Name, userName)];
await c.SignInAsync("CookieAuthenticationScheme", new ClaimsPrincipal(new ClaimsIdentity(claims, "CookieAuthenticationScheme")));
}
var Referer = Redirect("https://localhost:7207");
return Referer;
}
Затем на основном веб-сайте, использующем куки, я добавил следующее в Program.cs
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\KeyLocation"))
.SetApplicationName("SharedCookieApp");
builder.Services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
});
Однако кука, созданная на сайте с аутентификацией Windows, не позволяет войти на основной веб-сайт.
Буду признателен за любую помощь.
Ответ или решение
Для реализации вашей задачи по единой аутентификации между двумя веб-сайтами с использованием Windows аутентификации и куки аутентификации, вам потребуется следовать нескольким шагам. Вы уже на верном пути, но давайте рассмотрим некоторые важные моменты и возможные улучшения в вашем коде.
Основные шаги:
-
Общие настройки Data Protection:
Убедитесь, что на обоих сайтах используется одна и та же конфигурация для Data Protection. Это включает в себя использование одного и того жеPersistKeysToFileSystem
иSetApplicationName
. Вы уже сделали это, добавив код в каждый из сайтов. Убедитесь, что путь@"c:\KeyLocation"
доступен для записи и чтения для обоих приложений. -
Настройка схемы аутентификации:
Обратите внимание, что вам нужно установить одно и то же имя куки для аутентификации на обоих сайтах. Это вы правильно указали как.AspNet.SharedCookie
. Убедитесь, что конфигурации аутентификации в обоих проектах совпадают. -
Создание и передача куки:
В коде контроллера вашего сайта с Windows аутентификацией убедитесь, что изначально вы создаете куки с правильными параметрами. Также убедитесь, что имя пользователя, используемое для созданияClaim
, точно соответствует тому, как оно настроено в ASP.NET Identity вашего другого сайта. Вот пример:public class HomeController : Controller { public async Task<IActionResult> Index() { var c = HttpContext; var userName = c.User.Identity?.Name; if (!string.IsNullOrEmpty(userName)) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, userName), new Claim(ClaimTypes.Role, "User") // Добавьте другие роли при необходимости }; var claimsIdentity = new ClaimsIdentity(claims, "CookieAuthenticationScheme"); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); // Убедитесь, что вы используете корректную схему аутентификации await c.SignInAsync("CookieAuthenticationScheme", claimsPrincipal); } return Redirect("https://localhost:7207"); } }
-
Настройка кросс-доменных куки:
Если ваши сайты развернуты на разных доменах (например, test.local и example.com), вам нужно будет убедиться, что браузер позволяет устанавливать куки для разных доменов. Это может потребовать настройки CORS и возможно применения метода сSameSite=None
для куки, если они кросс-доменные.builder.Services.ConfigureApplicationCookie(options => { options.Cookie.Name = ".AspNet.SharedCookie"; options.Cookie.SameSite = SameSiteMode.None; // Не забудьте это установить, если используются разные домены options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // Используйте Secure только при HTTPS });
Заключение
Обобщая, убедитесь, что:
- Общая путь для Data Protection на обоих сайтах совпадает.
- Используется одно и то же имя куки и схема аутентификации.
- Пользовательские роли и идентификация точно соответствуют вашему ASP.NET Identity.
- Если предполагается работа через разные домены, пройдите этап настройки заголовков и обеспечьте кросс-доменные куки.
После выполнения всех этих шагов ваша система аутентификации должна работать, позволяя пользователям одновременно входить как через Windows аутентификацию, так и через куки на вашем внешнем сайте.