ASP.NET应用中的Active Directory用户认证

在大型的ASP.NET应用程序中,经常使用表单认证(Forms Authentication)来处理用户认证过程。然而,有时会出现需要利用现有的Active Directory(AD)来实现用户认证的需求。在这种情况下,有两种解决方案:替换表单认证为Windows认证,或者绕过表单认证以使用Active Directory。如果存在对aspnet_Users.UserId或aspnet_Membership.UserId列的外键引用,第一种方案将不可行。

绕过表单认证

如果使用ASP.NET登录控件处理用户登录过程,那么可以通过"OnAuthenticate"事件来绕过表单认证。以下是C#代码示例:

protected void LoginUser_Authenticate(object sender, AuthenticateEventArgs e) { try { if (IsActiveDirectoryEnabled) { if (ActiveDirectoryConnector.IsUserLoggedIn(LoginUser.UserName, LoginUser.Password)) { e.Authenticated = true; } else { e.Authenticated = false; } } } catch (Exception ex) { e.Authenticated = false; LoginUser.FailureText = ex.Message; } }

该事件在登录页面的页面加载事件中注册:

protected void Page_Load(object sender, EventArgs e) { if (IsActiveDirectoryEnabled) { LoginUser.Authenticate += new AuthenticateEventHandler(LoginUser_Authenticate); } }

Active Directory设置

以下配置部分用于控制Active Directory连接和用户搜索条件:

<ldapConfiguration enabled="true" pageLevelSecurityCheck="false" server="192.168.246.128" domain="test.com" directoryPath="DC=test,DC=com" groupName="elixtrauser" filter="(and(objectCategory=person)(objectClass=user)(samaccountname=usertosearch))" filterReplace="usertosearch"> </ldapConfiguration>

其中:

  • enabled: 通过在登录页面的页面加载中注册"OnAuthenticate"事件,启用Active Directory认证过程。
  • pageLevelSecurityCheck: 指示是否需要在每个页面级别进行用户认证检查。
  • server: LDAP服务器名称或IP地址。
  • domain: 域名。
  • directoryPath: 用户所在的目录路径。
  • groupName: 只有指定的用户组才能登录。
  • filter 和 filterReplace: 用于在指定目录中搜索用户。

Active Directory连接器

这个类与Active Directory通信,并根据web.config文件中设置的配置搜索用户。"IsUserLoggedIn"方法用于此目的。以下是C#代码示例:

public static bool IsUserLoggedIn(string userName, string password) { try { if (ActiveDirectorySettings.Enabled) { int startIndex = userName.IndexOf("@"); if (startIndex >= 0) { userName = userName.Substring(0, startIndex); } DirectoryEntry ldapConnection = new DirectoryEntry("LDAP://" + ActiveDirectorySettings.Server + "/" + ActiveDirectorySettings.DirectoryPath, userName, password); DirectorySearcher searcher = new DirectorySearcher(ldapConnection); searcher.Filter = ActiveDirectorySettings.Filter.Replace("and", "&"); searcher.Filter = searcher.Filter.Replace(ActiveDirectorySettings.FilterReplace, userName); searcher.PropertiesToLoad.Add("memberOf"); searcher.PropertiesToLoad.Add("userAccountControl"); SearchResult directoryUser = searcher.FindOne(); if (directoryUser != null) { int flags = Convert.ToInt32(directoryUser.Properties["userAccountControl"][0].ToString()); if (!Convert.ToBoolean(flags & 0x0002)) { string desiredGroupName = ActiveDirectorySettings.GroupName.ToLower(); if (desiredGroupName != string.Empty) { desiredGroupName = "cn=" + desiredGroupName + ","; int numberOfGroups = directoryUser.Properties["memberOf"].Count; bool isWithinGroup = false; for (int i = 0; i < numberOfGroups; i++) { string groupName = directoryUser.Properties["memberOf"][i].ToString().ToLower(); if (groupName.Contains(desiredGroupName)) { isWithinGroup = true; break; } } if (!isWithinGroup) { throw new Exception("User [" + userName + "] is not a member of the desired group."); } } return true; } else { throw new Exception("User [" + userName + "] is inactive."); } } else { throw new Exception("User [" + userName + "] not found in the specified active directory path."); } } else { return true; } } catch (LdapException ex) { if (ex.ErrorCode == 49) { throw new Exception("Invalid user authentication. Please input a valid user name & password and try again.", ex); } else { throw new Exception("Active directory server not found.", ex); } } catch (DirectoryOperationException ex) { throw new Exception("Invalid active directory path.", ex); } catch (DirectoryServicesCOMException ex) { if (ex.ExtendedError == 8333) { throw new Exception("Invalid active directory path.", ex); } else { throw new Exception("Invalid user authentication. Please input a valid user name & password and try again.", ex); } } catch (System.Runtime.InteropServices.COMException ex) { throw new Exception("Active directory server not found.", ex); } catch (ArgumentException ex) { if (ex.Source == "System.DirectoryServices") { throw new Exception("Invalid search filter expression.", ex); } else { throw new Exception("Unhandled exception occurred while authenticating user using active directory.", ex); } } catch (Exception ex) { throw new Exception("Unhandled exception occurred while authenticating user using active directory.", ex); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485