C#开发中Windows域认证登录

吉日嘎了的Webform例子程序做的很好,但在我们公司,除了使用GPM通用权限管理自带的账户系统登录,还需要集成Windows域账户登录。对于如何实现,我思考了一段时间,大体的思路如下:

1、在GPM中创建的用户账号和其在Windows域中的账号一致,如域账号为Troy.Cui,那么GPM中登录userName也是Troy.Cui
2、GPM中的账号需要单独手工创建,因为涉及到的权限、角色的设定,如果使用域账号登录的时候,自动创建GPM的账号意义不大
3、不启用IIS中的Windows集成认证,因为我们还有一部分用户是没有域账号的,所以必须使用模拟域用户登录的方式进行认证
4、模拟域账号登录成功后,需要在GPM中增加一个DomainLogon的方法,直接使用域账号进行登录,无需密码。

昨天在实现的过程中,在DoNet.Business中增加了DomainLogon(string userName)的方法调用BaseUserManager.LogOnByUserName,但是在做模拟域用户登录的时候,一直报各种各样的错误:

1、There is no such object on the server.
2、0x80005000
3、A referral was returned from the server

最后通过参考《[URL=http://www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C]Howto: (Almost) Everything In Active Directory via C#[/URL]》和《[URL=http://www.cnblogs.com/netlover/archive/2011/03/30/1999836.html]Asp.Net模拟域验证登录及密码修改[/URL]》,最后终于调试通过,代码如下:

创建DomainSigin.aspx,在DomainSigin.aspx.cs中增加引用:using System.DirectoryServices;

<br/>/// <summary><br/>    /// 域用户登录<br/>    /// </summary><br/>    /// <param name="userName">用户名</param><br/>    /// <param name="password">密码</param><br/>    private void DomainUserLogOn(string userName, string password)<br/>    {<br/>        //China Only<br/>        //string lDAP = "OU=Users,OU=China,DC=CORP,DC=yourdomain,DC=com";<br/>        string lDAP = "DC=CORP,DC=yourdomain,DC=com";<br/>        <br/>        DirectoryEntry dirEntry = new DirectoryEntry();<br/>        dirEntry.Path = string.Format("LDAP://{0}", lDAP);<br/>        dirEntry.Username = "corpwaiglobal\\" + userName;<br/>        dirEntry.Password = password;<br/>        dirEntry.AuthenticationType = AuthenticationTypes.Secure;<br/>        <br/>        string checkInput = string.Empty;<br/><br/>        try<br/>        {<br/>            DirectorySearcher searcher = new DirectorySearcher(dirEntry);<br/>            searcher.Filter = String.Format("(&(objectClass=user)(samAccountName={0}))", userName);<br/>            System.DirectoryServices.SearchResult result = searcher.FindOne();<br/>            if (result != null)<br/>            {<br/>                // 正常登录<br/>                <br/>                try<br/>                {<br/>                    string statusCode = string.Empty;<br/>                    string statusMessage = "没有此用户。";<br/><br/>                    // 有什么权限的人才可以登录到系统<br/>                    string permissionItemCode = string.Empty;<br/><br/>                    // 登录验证<br/>                    string openId = Utilities.GetOpenId();<br/>                    BaseUserInfo userInfo = Utilities.DomainLogOn(userName);<br/><br/>                    // txtVerifyCode.Text = string.Empty;<br/>                    // 登录结果<br/>                    if (userInfo!=null)<br/>                    {<br/>                        this.AfterLogOn(userInfo);<br/>                        // 登录成功,重新定向到跳转的页面<br/>                        // Page.Response.Redirect(this.ReturnURL);<br/>                        // 若是单点登录,还需要把OpenId传递过去,这样在其他子网站里可以获取到OpenId,而不是用户名密码了,可以进行加密登录了<br/>                        if (!string.IsNullOrEmpty(this.ReturnURL) && !string.IsNullOrEmpty(userInfo.OpenId))<br/>                        {<br/>                            if (this.ReturnURL.IndexOf('?') > 0)<br/>&nb
sp;                           {<br/>                                this.ReturnURL = this.ReturnURL + "&OpenId=" + userInfo.OpenId;<br/>                            }<br/>                            else<br/>                            {<br/>                                this.ReturnURL = this.ReturnURL + "?OpenId=" + userInfo.OpenId;<br/>                            }<br/>                        }<br/>                        Response.Redirect(this.ReturnURL, false);<br/>                    }<br/>                    else<br/>                    {<br/>                        checkInput = "<script>alert('提示信息:" + statusMessage + "');</script>";<br/>                        Page.ClientScript.RegisterStartupScript(this.GetType(), "message", checkInput);<br/>                        this.txtUserName.Focus();<br/>                    }<br/>                }<br/>                catch (System.Exception exception)<br/>                {<br/>                    Page.Response.Write(exception.Message);<br/>                    checkInput = "<script>alert('提示信息:登录失败,请检查你的用户名和密码是否输入有误。');</script>";<br/>                    Page.ClientScript.RegisterStartupScript(this.GetType(), "message", checkInput);<br/>                    this.txtUserName.Focus();<br/>                }<br/>            }<br/>            dirEntry.Close();<br/>        }<br/>        catch (Exception ex)<br/>        {<br/>            Page.Response.Write(ex.Message);<br/>            checkInput = "<script>alert('提示信息:登录失败,请检查你的用户名和密码是否输入有误。');</script>";<br/>            Page.ClientScript.RegisterStartupScript(this.GetType(), "message", checkInput);<br/>            this.txtUserName.Focus();<br/>        }<br/>    }<br/>

坦白的说,这么实现的话,对DotNet.Business部分暴漏出来一个无需密码的LogOnByUserName登录,的确是一个风险,最好的做法是把域验证的部分也放到DotNet.Business,但是这么做,又有缺点,会对不需要域认证的用户早成负担。

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据