Watin Windows Аутентификация - PullRequest
5 голосов
/ 14 июля 2009

Я пытаюсь написать тесты Watin для приложения для внутренней сети, использующего встроенную аутентификацию. Веб-страница, которую я пытаюсь проверить, печатает Page.User.Identity.Name.

Вот код из моего теста:

if (Win32.LogonUser(u.UserName, u.Domain, u.Password, 2 /*LOGON32_LOGON_INTERACTIVE*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out hToken))
            {
                if (Win32.DuplicateToken(hToken, 2, out hTokenDuplicate))
                {
                    WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);
                    WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();  

                    Console.WriteLine(WindowsIdentity.GetCurrent().Name);

                    using (IE ie = new IE(url))
                    {
                        Console.WriteLine(ie.ContainsText(u.UserName));
                        ie.AutoClose = false;
                    }

                    impersonationContext.Undo();
                }
            }

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

Аналогичная проблема найдена по адресу:
Автоматическое тестирование сценариев авторизации, реализованных с помощью AzMan

1 Ответ

4 голосов
/ 14 июля 2009

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

Посмотрите следующие блоги для получения дополнительной информации и примера кода:

http://blogs.msdn.com/jimmytr/archive/2007/04/14/writing-test-code-with-impersonation.aspx

http://blogs.msdn.com/shawnfa/archive/2005/03/21/400088.aspx

Редактировать: у меня сегодня получилось. Хитрость заключается в том, что вам нужно разделить запуск IE и автоматизацию IE, так как вы не можете просто сделать их обоих одним ударом.

Первый запуск, т. Е. С использованием System.Diagnostics.Process. После того, как вы запустили IE, вы можете использовать код из здесь , чтобы присоединиться и поговорить с IE, используя имперсию

Вот код

    [TestMethod]
    public void TestMethod()
    {
        SecureString password = new SecureString();
        password.AppendChar('p');
        password.AppendChar('a');
        password.AppendChar('s');
        password.AppendChar('s');
        password.AppendChar('w');
        password.AppendChar('o');
        password.AppendChar('r');
        password.AppendChar('d');

        ProcessStartInfo psi = new ProcessStartInfo();
        psi.UserName = "localtest";
        psi.Password = password;
        psi.UseShellExecute = false;
        psi.LoadUserProfile = true;
        psi.FileName = "c:\\Program Files\\Internet Explorer\\iexplore.exe";
        psi.Arguments = "about:blank";

        Process proc = new Process();
        proc.StartInfo = psi;
        proc.Start();

        t.Join();

        proc.Kill(); 
    }

    private static void DoWorkAs(object o)
    {
        User u = o as User;


        IntPtr hToken = IntPtr.Zero;
        IntPtr hTokenDuplicate = IntPtr.Zero;

        if (Win32.LogonUser(u.UserName, u.Domain, u.Password, 2 /*LOGON32_LOGON_INTERACTIVE*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out hToken))
        {
            if (Win32.DuplicateToken(hToken, 2, out hTokenDuplicate))
            {
                WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);
                WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();

                // domain\username
                Console.WriteLine(" Thread 2 : " + WindowsIdentity.GetCurrent().Name);

                IE ie = IE.AttachToIE(Find.ByUrl("about:blank"));

                ie.GoTo(@"http://www.google.com/");
                ie.TextField(Find.ByName("q")).TypeText("WatiN");
                ie.Button(Find.ByName("btnG")).Click();

                Assert.IsTrue(ie.ContainsText("WatiN"));
                ie.GoTo("about:blank");

                //revert
                impersonationContext.Undo();
                Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            }
        }
        if (hToken != IntPtr.Zero) Win32.CloseHandle(hToken);
        if (hTokenDuplicate != IntPtr.Zero) Win32.CloseHandle(hTokenDuplicate);
    }

    public class User
    {
        public User(string u, string d, string p)
        {
            Domain = d;
            UserName = u;
            Password = p;
        }
        public string UserName;
        public string Domain;
        public string Password;
    }
    public class Win32
    {
        // P/Invoke snask
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out IntPtr phToken);

        [DllImport("advapi32.dll", SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
           SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool CloseHandle(IntPtr hHandle);

    }

Этот код нуждается в рефакторинге и выиграл работу в Vista с IE7 из-за ошибки IE, которая была исправлена ​​в IE8.

...