Как поддерживать аутентификацию NTLM с возвратом в ASP.NET MVC?
Как я могу реализовать следующее в приложении ASP.NET MVC:
- пользователь открывает веб-сайт интрасети
- пользователь молча аутентифицируется, если возможно
- если проверка подлинности NTLM не сработала, покажите регистрационную форму пользователю
- пользователь указывает пароль для входа и выбирает домен из списка предопределенных доменов
- пользователь аутентифицируется в коде с использованием AD
Я знаю, как реализовать 4 и 5, но не могу найти информацию о том, как объединить NTLM и формы.
Так что диалог NTLM для внутреннего входа/пароля никогда не отображается - прозрачная аутентификация или приятная страница входа в систему.
Как работать?
Следует ли запрашивать логин и пароль?
Могут ли ее текущие учетные данные (имя домена) использоваться без запроса ввода логина и пароля?
ОБНОВЛЕНИЕ для них, исследуя ту же проблему:
Когда я спрашивал об этом, я не совсем понял, как работает аутентификация NTLM внутри.
Важно понять, что если браузер пользователя не поддерживает NTLM должным образом или если поддержка NTLM отключена пользователем - сервер никогда не получит возможности обойти это.
Как работает проверка подлинности Windows:
- Клиент отправляет обычный HTTP-запрос на сервер
- Сервер отвечает HTTP-статусом 401 и указывает, что для доступа к ресурсам следует использовать аутентификацию NTLM.
- Клиент отправляет сообщение NTLM Type1
- Сервер отвечает сообщением NTLM Type2 с вызовом
- Клиент отправляет сообщение Type3 с ответом на вызов
- Сервер отвечает запрошенным фактическим содержимым
Как вы видите, браузер, не поддерживающий NTLM, не перейдет к шагу (3), вместо этого будет отображаться страница IIS с ошибкой 401.
Если у пользователя нет учетных данных, после отмены всплывающего диалогового окна проверки подлинности NTLM не будет продолжаться (3).
Таким образом, у нас нет возможности автоматически перенаправлять пользователей на пользовательскую страницу входа.
Единственная опция здесь - иметь страницу "шлюза", где мы решаем, должен ли пользователь поддерживать NTLM, и если да, перенаправитесь на домашнюю страницу, защищенную NTLM.
И если нет, укажите регистрационную форму и разрешите аутентификацию вручную, введя логин и пароль.
Решение обычно делается на основе IP-адресов пользователей и/или имени хоста, либо путем сопоставления диапазонов IP-адресов, либо путем проверки таблицы предопределенных IP-адресов.
Ответы
Ответ 1
Эта статья может заставить вас указать в правильном направлении. В основном у вас есть два приложения в двух виртуальных каталогах под одним и тем же именем хоста. В одном приложении используется проверка подлинности с помощью форм, в Windows используется Windows. Тот, который использует проверку подлинности Windows, создает допустимый файл cookie проверки подлинности и перенаправляется во второй виртуальный каталог.
Аутентификация смешанного режима ASP.NET
Ответ 2
У меня есть эта точная настройка в процессе производства, я настраиваю свой портал на использование FormsAuth и написали функцию, которая заставляет IP-адреса посетителей искать учетную запись пользователя, входящую в этот IP/ПК. Используя имя, которое я нахожу (например, DOMAIN\user
), я проверяю, что домен соответствует моему домену, и что имя пользователя/учетная запись действительны в моем поставщике FormsAth, используя Membership.GetUser(<user>)
. Если этот вызов возвращает совпадение, а пользователь IsApproved
, я создаю FormsAuthenticationTicket
и cookie для пользователя. У меня есть 400 человек в сети, и это работает отлично, единственные компьютеры, которые все еще находятся в системе (1. Пользователи без учетных записей на моем портале, 2. Несколько пользователей MAC/Linux, 3. Мобильные пользователи, которые не загрузились в сети и с помощью групповой политики их брандмауэр был высоким).
Ловушка для этого решения заключается в том, что для запроса пользовательского ПК требуется олицетворение учетной записи администратора домена, и вы используете неуправляемый код netapi32.dll.. p >
Вот код, который я использую (внешние вызовы функций не предоставляются, для краткости). Я попытался немного упростить это, так как у меня есть LOTS внешних вызовов.
string account = String.Empty;
string domain = String.Empty;
string user = String.Empty;
ImpersonateUser iu = new ImpersonateUser(); //Helper that Enabled Impersonation
if (iu.impersonateValidUser(StringHelper.GetAppSetting("DomainAccount"), StringHelper.GetAppSetting("DomainName"), StringHelper.GetEncryptedAppSetting("DomainAccountPassword")))
{
NetWorkstationUserEnum nws = new NetWorkstationUserEnum(); //Wrapper for netapi32.dll (Tested on Vista, XP, Win2K, Win2K3, Win2K8)
string host = nws.DNSLookup(Request.UserHostAddress); // netapi32.dll requires a host name, not an IP address
string[] users = nws.ScanHost(host); // Gets the users/accounts logged in
if (nws.ScanHost(host).Length > 0)
{
string workstationaccount = string.Empty;
if (host.IndexOf('.') == -1) // Pick which account to use, I have 99.9% success with this logic (only time doesn't work is when you run a interactive process as a admin e.g. Run As <process>).
{
workstationaccount = String.Format("{0}\\{1}$",StringHelper.GetAppSetting("DomainName"), host).ToUpper();
}
else
{
workstationaccount = String.Format("{0}\\{1}$", StringHelper.GetAppSetting("DomainName"), host.Substring(0, host.IndexOf('.'))).ToUpperInvariant();
}
account = users[users.Length - 1].Equals(workstationaccount) ? users[0] : users[users.Length - 1];
domain = account.Substring(0, account.IndexOf("\\"));
user = account.Substring(account.IndexOf("\\") + 1,
account.Length - account.IndexOf("\\") - 1);
}
iu.undoImpersonation(); // Disable Impersonation
}
Теперь, используя учетную запись, которую мы захватили в первой функции/процессе, мы теперь пытаемся проверить и решить, следует ли нам показывать логин или автоматический вход пользователя.
MembershipUser membershipUser = Membership.GetUser(user);
if (membershipUser != null && membershipUser.IsApproved)
{
string userRoles = string.Empty; // Get all their roles
FormsAuthenticationUtil.RedirectFromLoginPage(user, userRoles, true); // Create FormsAuthTicket + Cookie +
}
Я написал сообщение в блоге об этом давным-давно, вот ссылка на обертку для netapi32.dll и моего помощника олицетворения, который я представил в сообщении Загрузка исходного кода
Ответ 3
У вас не может быть NTLM и FormsAuthentication в одном приложении ASP.NET. Вам понадобятся два разных приложения в отдельных виртуальных каталогах.