.Net 关于摸拟登录 并在登录成功后 使用IE打开 一路曲折

开发工具:VS2008 .NET 2.0
项目类型:BS
项目需求:开发一个账号管理系统,包括用户注册,用户登录,账号管理,快速登录等功能。

简单的流程如下:用户在账号管理系统中注册一个自己的账号,登录账号管理系统,在账号管理功能中,录入相应系统的账号与密码(系统是客户公司内之前就已开发好的,有BS端的也有cs端的,这篇文章中只说BS系统),已录入账号与密码的系统可以快速登录(快速登录界面的感觉,就是用户点击一下相就系统的快速登录,就看见浏览器新开一个窗口进行登录,并跳转到主页面)

尝试过的解决方案:

解决方案一:

使用HttpClient 进行摸拟登录,登录成功后,使用 InternetSetCookie 与IE同步cookies, 最后使用 Response.Redirect(“”);进行跳转。

    //写入函数
    [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);

方案的问题: HttpClient摸拟登录成功后,打开IE跳转到首页时,Cookies 不能同步,导致跳转失败(登录失败);

失败方案

解决方案二:

方案二与方案一有很大的相似之处,不同的地方在于 方案一 中使用的是 Response.Redirect(); 进行跳转而方案二中使用 System.Diagnostics.Process.Start();

在测试的过程中发现,使用  System.Diagnostics.Process.Start(); 能够登录到一些验证简单的系统中一般说来就是一些企业级的嘛,像 163 邮箱就不能登录,人人网我在测试过程中也没有成功。

方案二应该能满足我项目的需求,因为客户暂时没有给出具体的网站地址,所以不好说得。所以标记为失败方案

解决方案三:

调用本地的IE浏览器,并发送数据,想想这种方案简单也好用,但是我忘记我是使用的BS项目了,所以还是做了个测试,下面贴出测试代码:

            var myIE = new InternetExplorer();
            myIE.Visible = true;

            object headers = "Content-Type: application/x-www-form-urlencoded" + Convert.ToChar(10) + Convert.ToChar(13) + "Referer:http://www.hao123.com/";
            object postData = Encoding.ASCII.GetBytes("url=http://entry.mail.163.com/coremail/fcg/ntesdoor2?lightweight=1&verifycookie=1&language=-1&style=15&username=" + txtUserID.Value.Trim() + "&password=" + txtPwd.Value.Trim());
            object nullArg = null;
            myIE.Navigate("http://reg.163.com/CheckUser.jsp", ref nullArg, ref nullArg, ref postData, ref headers);

如果项目是CS的,我觉得这种解决方案相当的不错,但是我客户需要的是BS,也就在此时,我犯了一下二,信心满满的将测试代码放在IIS上,让同事给测试一下,结果,他们的邮箱都在我的电脑上登录成功了,呵呵(虽然如此但是的确都是登录成功的了)

失败方案

解决方案四:

根据用户快速登录的网站,根据提交的siteid找到当前登录用户相应的用户名,密码,然后生成一个form 表单,再自动提交form表单,最后来一个指定的跳转

具体的代码如下:

            StringBuilder _txt = new StringBuilder("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n" +
            "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n" +
            "<head>\r\n" +
            "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n" +
            "<title>百姓网快速登录</title>\r\n" +
            "<style type=\"text/css\" >\r\n" +
             "body{ font-size:14px;}\r\n" +
            "</style>\r\n" +
            "<script src=\"/js/jquery.js\" type=\"text/javascript\"></script>\r\n" +
            "<script type=\"text/javascript\">\r\n" +
            "function quickLoginSubmit() {\r\n" +
                "if (status==0) {\r\n" +
                    "window.location.href = exeUrl;\r\n" +
                "}else if(status==1){\r\n" +
                 "    if (manageUrl) {\r\n" +
                  "       if(window.opener){\r\n" +
                  "      window.opener.window.setTimeout(\"loginWindow.location.href='\" + manageUrl + \"';\", 3000);\r\n" +
                   "     }else{\r\n" +
                   "         window.setTimeout(\"window.location.href='\" + manageUrl + \"';\", 3000);\r\n" +
                    "    }\r\n" +
                    "}\r\n" +
                    "    $(\"#loginForm\").submit();\r\n" +
                "}\r\n" +
            "}\r\n" +
            "</script>\r\n" +
            "<script type=\"text/javascript\"> \r\n" +
            "    var manageUrl = \"http://www.baixing.com/wo/postings/#active\";\r\n" +
            "    var exeUrl = \"http://www.baixing.com/auth/denglu/?src=headerHome\";\r\n" +
            "    var status = 1;\r\n" +
            "    setTimeout(\"quickLoginSubmit();\",2000);\r\n" +
            "</script>\r\n" +
            "</head>\r\n" +
            "<body>\r\n" +
            "<img src=\"images/load.gif\" align=\"absmiddle\" >正在登录,请稍等...\r\n" +
            "<form id=\"loginForm\" method=\"post\" name=\"loginForm\" action=\"http://www.baixing.com/auth/denglu/?src=headerHome\">\r\n" +
            "    <input value=\"账号\" type=\"hidden\" name=\"identity\" /><input value=\"密码\" type=\"hidden\" name=\"password\" /><input value=\"login\" type=\"hidden\" name=\"action\" /><input value=\"http://hangzhou.baixing.com/\" type=\"hidden\" name=\"redirect\" /><input type=\"hidden\" name=\"refer\" />\r\n" +
            "</form>\r\n" +
            "</body>\r\n" +
            "</html>\r\n");
            
             Response.Write(_txt);

在我的需求中,方案四是最合适的了。

成功方案  在此感谢 Launcher ,是 launcher 给我指引了正确的方向,呵呵 

在测试中发现,js 中的 XMLHttpRequest ,是不能修改Referer的值,虽然他有一个设置头的方法 ,代码如下:

<script type ="text/javascript">
        var xmlHttp = null;
    
        function createXMLHttpRequest() {
            if (xmlHttp == null) {
                if (window.XMLHttpRequest) {
                    //Mozilla 浏览器
                    xmlHttp = new XMLHttpRequest();
                } else if (window.ActiveXObject) {
                    // IE浏览器
                    try {
                        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
                    } catch (e) {
                        try {
                            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                        } catch (e) {
                        }
                    }
                }
            }
        }
        
        //发送数据
        function Post() {
            if (xmlHttp == null) {
                createXMLHttpRequest();
            }

            var data = "url=http%3A%2F%2Fentry.mail.163.com%2Fcoremail%2Ffcg%2Fntesdoor2%3Flightweight%3D1%26verifycookie%3D1%26language%3D-1%26style%3D15&username=challengesoflife&password=zhukun1989";

            xmlHttp.open("POST", "http://www.abc.com", true);
            xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xmlHttp.setRequestHeader("Referer", "http://www.a.com");
            xmlHttp.setRequestHeader("Origin", "http://www.b.com");
            xmlHttp.send(data);
        }
        
        //状态改变事件
        function onreadystatechange() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    alert('!!!');
                    
                    window.location.href = "http://www.abc.com";
                }
            } 
        }
    </script>

在此附加获取cookies的方法 ,是在网上找的,出处已忘记了

public List<Cookie> GetAllCookies(CookieContainer cc)
    {
        List<Cookie> lstCookies = new List<Cookie>();

        Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable",
            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField |
            System.Reflection.BindingFlags.Instance, null, cc, new object[] { });

        foreach (object pathList in table.Values)
        {
            SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list",
                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField
                | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });
            foreach (CookieCollection colCookies in lstCookieCol.Values)
                foreach (Cookie c in colCookies) lstCookies.Add(c);
        }

        return lstCookies;
    }
原文地址:https://www.cnblogs.com/challengesoflife/p/2870879.html