将 Selenium Webdriver 与 Windows 身份验证一起使用

软件测试 硒2 网络驱动程序
2022-02-03 17:34:51

我正在尝试为需要 Windows 身份验证的网站创建一些硒测试。我的第一个测试很容易启动并运行,但一旦系统提示输入凭据,它就会暂停。

有没有办法提供这些凭据,仍然允许我在所有主要浏览器上运行测试?

4个回答

我最终为 Firefox 创建了一个自定义配置文件并添加了 AutoAuth 插件。不是特别优雅,但它确实有效。归功于以下博客文章:

http://www.codemiller.com/post/5923640143/overcoming-auth-pop-ups

我发现 WebDriver 通过使用 Windows 模拟和 IE 的自动登录功能与 IE 9 和 Windows / NTLM 身份验证一起使用。
可以在此处找到您需要调用的 impersonateValidUser 方法的示例:在代码中模拟特定用户

本质上,您想要执行以下操作(确保 IE 9 配置为“自动登录”):

impersonateValidUser("DifferentUser", "DOMAIN", "Password");
// WebDriver now logged in as "DifferentUser"
IWebDriver webDriver = new InternetExplorerDriver();

要恢复到运行测试 / Selenium RC 的用户,只需调用:

undoImpersonation();

对于Firefox这有效:

C#

var profile = new FirefoxProfile();
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", ".companyname.com");

return new FirefoxDriver(profile);

Python

from selenium.webdriver import Firefox, FirefoxProfile

profile = FirefoxProfile()
profile.set_preference('network.automatic-ntlm-auth.trusted-uris', '.companyname.com')

return Firefox(firefox_profile=profile)

模仿很棘手。我没有用 Selenium 做到这一点,但我用 WatiN 和 IE 做到了。我将发布我的 WatiN 解决方案,您可以使用 Selemium(我认为)。

诀窍是您需要将 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);


                // This is WatiN code, you will need to replace with Selenium
                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);

    }

此代码需要重构,并且无法在带有 IE7 的 Vista 上运行,因为 IE8 中已修复一个 IE 错误。