Asp.net集成Windows域账户登陆
-
最近领导让修改一个asp小系统,由于自己对asp.net比较熟悉而对asp很是陌生!虽然asp的源代码也有,只是修改一下实现CRUD即可,但也是很痛苦的一件事啊!于是一上午都在看代码,郁闷ing.由于公司的电脑都是在域中(Microsoft的外包公司,域名就不说了,估计很多都知道的,哈哈),于是突发奇想,能不能通过AD中用户和密码对系统进行身份验证呢?经过Google总算搜出一篇文章来(还是微软网站上的,URL),按照葫芦画瓢总算是在VS2008中调试成功了!顺便分享一下算是自己的经验吧!
1. 创建Web Site,添加一个类,代码如下
Code
1using System;
2using System.Text;
3using System.Collections;
4using System.DirectoryServices;
5
6namespace FormsAuth
7{
8 public class LdapAuthentication
9 {
10 private String _path;
11 private String _filterAttribute;
12
13 public LdapAuthentication(String path)
14 {
15 _path = path;
16 }
17
18 public bool IsAuthenticated(String domain, String username, String pwd)
19 {
20 String domainAndUsername = domain + @"\" + username;
21 DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
22
23 try
24 { //Bind to the native AdsObject to force authentication.
25 Object obj = entry.NativeObject;
26
27 DirectorySearcher search = new DirectorySearcher(entry);
28
29 search.Filter = "(SAMAccountName=" + username + ")";
30 search.PropertiesToLoad.Add("cn");
31 SearchResult result = search.FindOne();
32
33 if (null == result)
34 {
35 return false;
36 }
37
38 //Update the new path to the user in the directory.
39 _path = result.Path;
40 _filterAttribute = (String)result.Properties["cn"][0];
41 }
42 catch (Exception ex)
43 {
44 throw new Exception("Error authenticating user. " + ex.Message);
45 }
46
47 return true;
48 }
49
50 public String GetGroups()
51 {
52 DirectorySearcher search = new DirectorySearcher(_path);
53 search.Filter = "(cn=" + _filterAttribute + ")";
54 search.PropertiesToLoad.Add("memberOf");
55 StringBuilder groupNames = new StringBuilder();
56
57 try
58 {
59 SearchResult result = search.FindOne();
60
61 int propertyCount = result.Properties["memberOf"].Count;
62
63 String dn;
64 int equalsIndex, commaIndex;
65
66 for (int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
67 {
68 dn = (String)result.Properties["memberOf"][propertyCounter];
69
70 equalsIndex = dn.IndexOf("=", 1);
71 commaIndex = dn.IndexOf(",", 1);
72 if (-1 == equalsIndex)
73 {
74 return null;
75 }
76
77 groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
78 groupNames.Append("|");
79
80 }
81 }
82 catch (Exception ex)
83 {
84 throw new Exception("Error obtaining group names. " + ex.Message);
85 }
86 return groupNames.ToString();
87 }
88 }
89}
90
1using System;
2using System.Text;
3using System.Collections;
4using System.DirectoryServices;
5
6namespace FormsAuth
7{
8 public class LdapAuthentication
9 {
10 private String _path;
11 private String _filterAttribute;
12
13 public LdapAuthentication(String path)
14 {
15 _path = path;
16 }
17
18 public bool IsAuthenticated(String domain, String username, String pwd)
19 {
20 String domainAndUsername = domain + @"\" + username;
21 DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
22
23 try
24 { //Bind to the native AdsObject to force authentication.
25 Object obj = entry.NativeObject;
26
27 DirectorySearcher search = new DirectorySearcher(entry);
28
29 search.Filter = "(SAMAccountName=" + username + ")";
30 search.PropertiesToLoad.Add("cn");
31 SearchResult result = search.FindOne();
32
33 if (null == result)
34 {
35 return false;
36 }
37
38 //Update the new path to the user in the directory.
39 _path = result.Path;
40 _filterAttribute = (String)result.Properties["cn"][0];
41 }
42 catch (Exception ex)
43 {
44 throw new Exception("Error authenticating user. " + ex.Message);
45 }
46
47 return true;
48 }
49
50 public String GetGroups()
51 {
52 DirectorySearcher search = new DirectorySearcher(_path);
53 search.Filter = "(cn=" + _filterAttribute + ")";
54 search.PropertiesToLoad.Add("memberOf");
55 StringBuilder groupNames = new StringBuilder();
56
57 try
58 {
59 SearchResult result = search.FindOne();
60
61 int propertyCount = result.Properties["memberOf"].Count;
62
63 String dn;
64 int equalsIndex, commaIndex;
65
66 for (int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
67 {
68 dn = (String)result.Properties["memberOf"][propertyCounter];
69
70 equalsIndex = dn.IndexOf("=", 1);
71 commaIndex = dn.IndexOf(",", 1);
72 if (-1 == equalsIndex)
73 {
74 return null;
75 }
76
77 groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
78 groupNames.Append("|");
79
80 }
81 }
82 catch (Exception ex)
83 {
84 throw new Exception("Error obtaining group names. " + ex.Message);
85 }
86 return groupNames.ToString();
87 }
88 }
89}
90
2. 修改Global.ascx文件增加Application_AuthenticateRequest方法,代码如下
Code
1 void Application_AuthenticateRequest(Object sender, EventArgs e)
2 {
3 String cookieName = FormsAuthentication.FormsCookieName;
4 HttpCookie authCookie = Context.Request.Cookies[cookieName];
5
6 if (null == authCookie)
7 {//There is no authentication cookie.
8 return;
9 }
10
11 FormsAuthenticationTicket authTicket = null;
12
13 try
14 {
15 authTicket = FormsAuthentication.Decrypt(authCookie.Value);
16 }
17 catch (Exception)
18 {
19 //Write the exception to the Event Log.
20 return;
21 }
22
23 if (null == authTicket)
24 {//Cookie failed to decrypt.
25 return;
26 }
27
28 //When the ticket was created, the UserData property was assigned a
29 //pipe-delimited string of group names.
30 String[] groups = authTicket.UserData.Split(new char[] { '|' });
31
32 //Create an Identity.
33 System.Security.Principal.GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");
34
35 //This principal flows throughout the request.
36 GenericPrincipal principal = new GenericPrincipal(id, groups);
37
38 Context.User = principal;
39
40 }
1 void Application_AuthenticateRequest(Object sender, EventArgs e)
2 {
3 String cookieName = FormsAuthentication.FormsCookieName;
4 HttpCookie authCookie = Context.Request.Cookies[cookieName];
5
6 if (null == authCookie)
7 {//There is no authentication cookie.
8 return;
9 }
10
11 FormsAuthenticationTicket authTicket = null;
12
13 try
14 {
15 authTicket = FormsAuthentication.Decrypt(authCookie.Value);
16 }
17 catch (Exception)
18 {
19 //Write the exception to the Event Log.
20 return;
21 }
22
23 if (null == authTicket)
24 {//Cookie failed to decrypt.
25 return;
26 }
27
28 //When the ticket was created, the UserData property was assigned a
29 //pipe-delimited string of group names.
30 String[] groups = authTicket.UserData.Split(new char[] { '|' });
31
32 //Create an Identity.
33 System.Security.Principal.GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");
34
35 //This principal flows throughout the request.
36 GenericPrincipal principal = new GenericPrincipal(id, groups);
37
38 Context.User = principal;
39
40 }
3. 修改Web.config,代码如下
Code
1<system.web>
2 <authentication mode="Forms">
3 <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/" >
4 </forms>
5 </authentication>
6 <authorization>
7 <deny users="?" />
8 <allow users="*" />
9 </authorization>
10 <identity impersonate="true" />
11 </system.web>
12
1<system.web>
2 <authentication mode="Forms">
3 <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/" >
4 </forms>
5 </authentication>
6 <authorization>
7 <deny users="?" />
8 <allow users="*" />
9 </authorization>
10 <identity impersonate="true" />
11 </system.web>
12
4. 为匿名身份验证配置IIS
默认网站——虚拟目录——目录安全——匿名访问和身份验证——编辑——去掉默认的IUSER账户,IUSER 默认状态下没有访问AD的权限,因此需要替换成一个具有AD访问权限的用户!IIS6和IIS7设置步骤有点不同可以参考下面的图片!
创建Logon.aspx来进行测试了啊,代码伺候!
HTML 代码
Code
1<form id="Login" method="post" runat="server">
2 Your Domain information is:<asp:Label runat="server" ID="Domainname"></asp:Label>
3 <br />
4 <asp:Label ID="Label1" Runat=server >Domain:</asp:Label>
5 <asp:TextBox ID="txtDomain" Runat=server ></asp:TextBox><br>
6 <asp:Label ID="Label2" Runat=server >Username:</asp:Label>
7 <asp:TextBox ID=txtUsername Runat=server ></asp:TextBox><br>
8 <asp:Label ID="Label3" Runat=server >Password:</asp:Label>
9 <asp:TextBox ID="txtPassword" Runat=server TextMode=Password></asp:TextBox><br>
10 <asp:Button ID="btnLogin" Runat=server Text="Login" OnClick="Login_Click"></asp:Button><br>
11 <asp:Label ID="errorLabel" Runat=server ForeColor=#ff3300></asp:Label><br>
12 <asp:CheckBox ID=chkPersist Runat=server Text="Persist Cookie" />
13 </form>
1<form id="Login" method="post" runat="server">
2 Your Domain information is:<asp:Label runat="server" ID="Domainname"></asp:Label>
3 <br />
4 <asp:Label ID="Label1" Runat=server >Domain:</asp:Label>
5 <asp:TextBox ID="txtDomain" Runat=server ></asp:TextBox><br>
6 <asp:Label ID="Label2" Runat=server >Username:</asp:Label>
7 <asp:TextBox ID=txtUsername Runat=server ></asp:TextBox><br>
8 <asp:Label ID="Label3" Runat=server >Password:</asp:Label>
9 <asp:TextBox ID="txtPassword" Runat=server TextMode=Password></asp:TextBox><br>
10 <asp:Button ID="btnLogin" Runat=server Text="Login" OnClick="Login_Click"></asp:Button><br>
11 <asp:Label ID="errorLabel" Runat=server ForeColor=#ff3300></asp:Label><br>
12 <asp:CheckBox ID=chkPersist Runat=server Text="Persist Cookie" />
13 </form>
Code
1protected void Login_Click(object sender, EventArgs e)
2 {
3 String adPath = "LDAP://Here is the full domain name"; //Fully-qualified Domain Name
4 LdapAuthentication adAuth = new LdapAuthentication(adPath);
5 try
6 {
7 if (true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
8 {
9 String groups = adAuth.GetGroups();
10
11 //Create the ticket, and add the groups.
12 bool isCookiePersistent = chkPersist.Checked;
13 FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,
14 DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups);
15
16 //Encrypt the ticket.
17 String encryptedTicket = FormsAuthentication.Encrypt(authTicket);
18
19 //Create a cookie, and then add the encrypted ticket to the cookie as data.
20 HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
21
22 if (true == isCookiePersistent)
23 authCookie.Expires = authTicket.Expiration;
24
25 //Add the cookie to the outgoing cookies collection.
26 Response.Cookies.Add(authCookie);
27
28 //You can redirect now.
29 Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false));
30 }
31 else
32 {
33 errorLabel.Text = "Authentication did not succeed. Check user name and password.";
34 }
35 }
36 catch (Exception ex)
37 {
38 errorLabel.Text = "Error authenticating. " + ex.Message;
39 }
40
41 }
1protected void Login_Click(object sender, EventArgs e)
2 {
3 String adPath = "LDAP://Here is the full domain name"; //Fully-qualified Domain Name
4 LdapAuthentication adAuth = new LdapAuthentication(adPath);
5 try
6 {
7 if (true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
8 {
9 String groups = adAuth.GetGroups();
10
11 //Create the ticket, and add the groups.
12 bool isCookiePersistent = chkPersist.Checked;
13 FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,
14 DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups);
15
16 //Encrypt the ticket.
17 String encryptedTicket = FormsAuthentication.Encrypt(authTicket);
18
19 //Create a cookie, and then add the encrypted ticket to the cookie as data.
20 HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
21
22 if (true == isCookiePersistent)
23 authCookie.Expires = authTicket.Expiration;
24
25 //Add the cookie to the outgoing cookies collection.
26 Response.Cookies.Add(authCookie);
27
28 //You can redirect now.
29 Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false));
30 }
31 else
32 {
33 errorLabel.Text = "Authentication did not succeed. Check user name and password.";
34 }
35 }
36 catch (Exception ex)
37 {
38 errorLabel.Text = "Error authenticating. " + ex.Message;
39 }
40
41 }
由于上面设计比较多的代码,没有贴出图片,下面就是IIS6和IIS7配置的几张截图