A-A+
.NET与AD-与站点结合(一)
假设现在有一个需求:将AD中的人员名称定时同步至某个站点的数据库内,该站点非匿名访问,登录时需要进行域验证。
针对这个需求,需要至少一张数据库表(在此命名为TB_UserInfo),表结构设计如下:
字段名称 | 类型 | 备注 |
---|---|---|
UserID | varchar | 主键,用户ID,与AD中user的ID属性相同 |
UserName | varchar | 用户名称,与AD中user的sAMAccountName属性相同 |
DisplayName | Varchar | 用户显示名称,与AD中user的DisplayName属性相同 |
同步程序设计如下:
- 使用Windows Service或者桌面应用程序开发,安装至服务器后设置为开机自启动。
- 假设数据量在千条之内,则将AD中指定节点下的人员数据和数据库中表TB_UserInfo中的数据读取至内存集合(ADUserCollection和DBUserCollection)中,在数据库中更新属于ADUserCollectio且属于DBUserCollection的数据;在数据库中删除属于DBUserCollection但不属于ADUserCollection的数据;在数据库中新增属于ADUserCollection但不属于DBUserCollection的数据。
示例代码如下:
- /// <summary>
- /// 人员信息
- /// </summary>
- public class UserInfo
- {
- /// <summary>
- /// 人员ID
- /// </summary>
- public string UserID { get ; set; }
- /// <summary>
- /// 用户名
- /// </summary>
- public string UserName { get; set; }
- /// <summary>
- /// 显示名称
- /// </summary>
- public string DisplayName { get; set; }
- }
- /// <summary>
- /// 为UserInfo自定义的比较类
- /// </summary>
- public class UserInfoComparer : IEqualityComparer<UserInfo>
- {
- public bool Equals(UserInfo x, UserInfo y)
- {
- return x.UserID == y.UserID;
- }
- public int GetHashCode(UserInfo userInfo)
- {
- return userInfo.UserID.GetHashCode();
- }
- }
- /// <summary>
- /// 将活动目录中的人员信息同步至数据库
- /// </summary>
- public void SynchronizationADUserToDB()
- {
- List<UserInfo> lstADUser = GetUserFromAD();
- List<UserInfo> lstDBUser = GetUserFromDB();
- //取得存在于DB中但不存在于AD中的人员集合
- List<UserInfo> lstImportUser =
- lstDBUser.Except(lstADUser, new UserInfoComparer()).ToList();
- foreach (UserInfo userInfo in lstImportUser)
- {
- DeleteUserToDB (userInfo);
- }
- //取得存在于AD中且存在于DB中的人员集合
- lstImportUser = lstADUser.Intersect(lstDBUser, new UserInfoComparer()).ToList();
- foreach (UserInfo userInfo in lstImportUser)
- {
- UpdateUserToDB (userInfo);
- lstADUser.Remove(userInfo);
- }
- //取得存在于AD中但不存在于DB中的人员集合
- lstImportUser = lstADUser;
- foreach (UserInfo userInfo in lstImportUser)
- {
- InsertUserToDB(userInfo);
- }
- }
站点的程序设计比较简单,只需要在登录时先验证人员是否存在于数据库中,然后再验证是否可以使用输入的凭证信息登录AD,示例代码如下:
- //通过输入的账户信息验证是否存在于数据库中
- ……
- //验证是否可以使用输入的账户信息登录AD
- DirectoryEntry entry = null;
- try
- {
- entry = new DirectoryEntry(strLDAP, strUserName, strPWD, AuthenticationTypes.Secure);
- object objID = entry.NativeGuid;
- return true;
- }
- catch
- {
- return false;
- }
- //如果既存在于数据库同时也可以登录AD,则该用户为合法用户
至此,所假设的需求已经实现。如果AD内user数量巨大,最好不要使用此示例中所提供的导入方法,嵌套遍历会使效率极其低下。