Как поддержать проверку подлинности NTLM с резервной формой в ASP.NET MVC? - PullRequest
19 голосов
/ 27 октября 2010

Как реализовать в приложении ASP.NET MVC следующее:

  1. пользователь открывает интранет-сайт
  2. пользователь проходит аутентификацию без предупреждения, если это возможно
  3. если аутентификация NTLM не сработала, покажите пользователю форму входа
  4. пользователь указывает пароль для входа и выбирает домен из списка предопределенных доменов
  5. пользователь аутентифицирован в коде с использованием AD

Я знаю, как реализовать 4 и 5, но не могу найти информацию о том, как объединить NTLM и формы. Так что диалоговое окно ввода логина и пароля NTLM никогда не отображается - прозрачная аутентификация или приятная страница входа.

Как должно работать? Нужно ли пользователю спрашивать логин и пароль? Можно ли использовать ее текущие учетные данные (имя пользователя домена) без запроса ввода логина и пароля?

ОБНОВИТЬ для них, исследуя ту же проблему:

Когда я спрашивал об этом, я не до конца понимал, как внутренне работает аутентификация NTLM. Здесь важно понимать, что если браузер пользователя не поддерживает должным образом NTLM или если поддержка NTLM отключена пользователем - сервер никогда не получит возможность обойти это.

Как работает аутентификация Windows:

  1. Клиент отправляет обычный HTTP-запрос на сервер
  2. Сервер отвечает HTTP-статусом 401 и указывает, что для доступа к ресурсам должна использоваться аутентификация NTLM
  3. Клиент отправляет сообщение NTLM Type1
  4. Сервер отвечает сообщением NTLM Type2 с запросом
  5. Клиент отправляет сообщение типа 3 с ответом на запрос
  6. Сервер отвечает с фактическим запрошенным контентом

Как вы видите, браузер, не поддерживающий NTLM, не перейдет к шагу (3), вместо этого пользователю будет показана страница 401, сгенерированная IIS.

Если у пользователя нет учетных данных, после отмены всплывающего диалогового окна проверки подлинности NTLM браузер также не будет продолжать (3).

Таким образом, у нас нет возможности автоматически перенаправлять пользователей на пользовательскую страницу входа.

Единственный вариант здесь - это иметь страницу «шлюза», где мы решаем, должен ли пользователь поддерживать NTLM, и если это так, перенаправить на домашнюю страницу, защищенную NTLM.

А если нет, покажите форму входа и разрешите аутентификацию, введя логин и пароль вручную.

Решение обычно принимается на основе IP-адреса пользователя и / или имени хоста либо путем сопоставления диапазонов IP-адресов, либо путем проверки таблицы предварительно определенных IP-адресов.

Ответы [ 3 ]

8 голосов
/ 27 октября 2010

Эта статья может указать вам в правильном направлении. В основном у вас есть два приложения в двух виртуальных каталогах под одним именем хоста. Одно приложение использует проверку подлинности с помощью форм, другое - Windows. При использовании проверки подлинности Windows создается допустимый файл cookie проверки подлинности формы и перенаправляется во второй виртуальный каталог.

Аутентификация в смешанном режиме ASP.NET

2 голосов
/ 27 октября 2010

У меня есть такая точная настройка на производстве, я настроил свой портал для использования FormsAuth и написал функцию, которая берет IP-адрес посетителей, чтобы найти учетную запись пользователя, который вошел на этот IP / ПК.Используя найденное мной имя (например, DOMAIN\user), я проверяю, совпадает ли домен с моим доменом и что имя / учетная запись пользователя действительна в моем провайдере FormsAth с использованием Membership.GetUser(<user>).Если этот вызов возвращает совпадение и пользователь IsApproved, я создаю FormsAuthenticationTicket & cookie для пользователя.У меня более 400 человек в сети, и это работает отлично, единственные компьютеры, которые все еще входят в систему (1. Пользователи без учетных записей на моем портале, 2. Несколько пользователей MAC / Linux, 3. Мобильные пользователи, которые не загружались в сетии если групповая политика включила высокий уровень защиты брандмауэра).

Подвох этого решения заключается в том, что для запроса пользователей ПК олицетворение учетной записи администратора домена и что вы используете неуправляемый код netapi32.dll .

Вот код, который я использую (для краткости внешние вызовы функций не предусмотрены).Я попытался немного упростить это, поскольку имею много внешних вызовов.

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 и мой помощник по подражанию, который я предоставил вpost Исходный код Скачать

0 голосов
/ 27 октября 2010

Нельзя использовать NTLM и FormsAuthentication в одном приложении ASP.NET.Вам понадобятся два разных приложения в отдельных виртуальных каталогах.

...