Могу ли я выдать себя за клиента, прошедшего проверку подлинности с помощью форм, и установить надежное соединение с SQL Server? - PullRequest
11 голосов
/ 09 февраля 2011

Вот что я пытался сделать

Создайте приложение ASP.NET MVC 3 с проверкой подлинности с помощью форм и членством в активном каталоге.Веб-сервер и база данных - это разные физические серверы, следовательно, двойной переход.

Я думал, что ответом была эта старая статья о ограниченном делегировании и передаче протокола ?До сих пор я не смог заставить работать эту технику.

Я тестирую это на своем компьютере DEV (Windows 7, IIS7) для веб-сервера, прежде чем развертывать в Windows 2008 (IIS7) внастройка производства.Будет ли Windows 2008 иметь значение?

Что работает и что не получается

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

public void AsUser(Action action)
    {
        using (var id = new WindowsIdentity(User.Identity.Name + @"@example.com"))
        {
            WindowsImpersonationContext context = null;
            try
            {
                context = id.Impersonate();
                action.Invoke();
            }
            catch (Exception ex)
            {
                // ex.Message is The type initializer for System.Data.SqlClient.SqlConnection threw an exception
                // buried inner exeption is Requested registry access is not allowed
            }
            finally
            {
                if (context != null)
                {
                    context.Undo();
                }
            }
        }
    }

Это не удается, за исключением того, что я полагаю, что у меня проблемы с настройкой на локальном сервере DEV.Внутреннее исключение - Requested registry access is not allowed.

Если я установлю точку останова и осмотрю WindowsIdentity после вызова Impersonate(), я вижу, что ImpersonationLevel установлен на Identification.Это похоже на подсказку, что он настроен неправильно.Кто-нибудь может подтвердить?

Я на правильном пути, и это вообще возможно настроить? Любые указатели приветствуются.

Ответы [ 5 ]

5 голосов
/ 22 февраля 2011

Я думаю, вы на правильном пути.Вам просто нужно больше устранить неполадки в настройке перехода протокола.

Я предполагаю, что вы правильно настроили поставщика членства в Active Directory, чтобы вы могли успешно войти на свою веб-страницу, используя имя пользователя и пароль активного каталога.Если это не так, пожалуйста, проигнорируйте остальную часть моего ответа:)

Из того, что я увидел в вашем вопросе, вы получили токен своего пользователя, используя S4USelf от WindowsIdentity.Затем вы используете S4UProxy для передачи олицетворенного токена серверу SQL.Поскольку вы сказали, что получили только ImpersonationLevel.Identification, это означает, что вы не смогли выполнить переход по протоколу.

Вы должны понимать, что разрешение одной машине выполнять переход по протоколу в домене - это очень высокая привилегия.Предоставление серверу для перехода по протоколу почти означает, что вы доверяете этому серверу почти как контроллеру домена.Вам нужно сознательно принять это решение в AD, чтобы сервер имел такую ​​возможность, и вы должны быть администратором domian, чтобы внести это изменение.Если вы этого не сделали, вы, вероятно, неправильно настроили свою вещь.

Есть пара вещей, которые нужно проверить.

Сначала убедитесь, что вы выбрали "Доверять этому компьютеру возможность делегированияТолько указанные службы "и затем вы выбрали" выберите Использовать любой протокол аутентификации "в своей учетной записи службы.Вы можете создать учетную запись домена. Здесь - ссылка на то, как создать служебную учетную запись для ASP.NET.Помните, вам нужна учетная запись домена.После создания учетной записи службы домена обязательно перейдите на вкладку делегирования этой учетной записи и выберите правильные параметры.

Во-вторых, необходимо убедиться, что имена участников-служб установлены правильно.Я понимаю, что в размещенной вами ссылке упоминается только имя участника-службы вашей учетной записи службы ASP.NET.На самом деле, вы также должны убедиться, что учетная запись службы на вашем сервере SQL также настроена правильно.Иными словами, Windows вообще не будет использовать аутентификацию Kerberos.Он вернется к использованию NTLM.Существует множество деталей для правильной настройки имени участника-службы на сервере SQL.Вы можете сначала проверить здесь и посмотреть, повезет ли вам.По моему опыту, большинство администраторов баз данных не знают, как их правильно настроить.Они даже не знают об этом, потому что большинство приложений работают нормально с NTLM.Необходимо обратить внимание на учетную запись службы сервера SQL и номер порта, который она использует.

В-третьих, вам нужно убедиться, что ничто не отключает делегирование Kerberos.Некоторые конфиденциальные учетные записи AD по умолчанию запрещены для делегирования.Например, встроенная учетная запись администратора.Итак, вам лучше использовать некоторые другие обычные учетные записи пользователей для целей тестирования.

ОБНОВЛЕНИЕ

Я только что нашел еще одну статью , обучающую вас, как настроитьпротокол перехода для ASP.NET.В нем упоминалось, что вам необходимо предоставить право TCB учетной записи службы IIS, чтобы убедиться, что она может создавать WindowsIdentity типа Impersonation.Вы можете дать ему шанс.

2 голосов
/ 22 февраля 2011

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

public class ImpersonationHelper : IDisposable
    {
        private const int LOGON32_LOGON_INTERACTIVE = 2;
        private const int LOGON32_PROVIDER_DEFAULT = 0;
        private WindowsImpersonationContext _impersonationContext;
        private string _userName;
        private string _domain;
        private string _password;

        [DllImport("advapi32.dll")]
        public static extern int LogonUserA(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public ImpersonationHelper(string domain, string userName, string password)
        {
            _userName = userName;
            _domain = domain;
            _password = password;
        }

        public void Start()
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(_userName, _domain, _password, LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        _impersonationContext = tempWindowsIdentity.Impersonate();
                        if (_impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
        }

        #region IDisposable Members

        void IDisposable.Dispose()
        {
            if (_impersonationContext != null)
            {
                _impersonationContext.Undo();
            }
        }

        #endregion
    }
1 голос
/ 22 февраля 2011

Я думаю, что вы определили проблему, но никто не упомянул ее.Проблема «двойного прыжка» не позволит вам сделать это.Это невозможно.Есть много людей, которые написали об этом, например, Скотт Форсайт .

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

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

Я думаю, что совершенно очевидно, что вы не можете передавать свои учетные данные дальше, чем первое соединение.

1 голос
/ 21 февраля 2011

Вам также следует узнать у администрации AD, разрешено ли олицетворение.Политика AD моей компании не допускает олицетворения.

1 голос
/ 21 февраля 2011

Включили ли вы олицетворение на компьютере с Windows 7 или Windows 2008? В этой статье рассказывается, как его настроить. http://technet.microsoft.com/en-us/library/cc730708(WS.10).aspx. Кроме того, вы используете 32-разрядную или 64-разрядную версию?

...