企业信息化系统基础活动目录(AD)
– 同步企业现有组织结构的方法
微软的产品是越来越多,如果要流畅的把微软的产品集成的使用好,AD活动目录是必须的,比如我们企业中可能用到sharepoint portal server ,也可能用到exchange webmail 、还可能用到reporting service等等,但一定也是用到现有的一些系统,如CRM、OA、客户服务管理系统等,采用FORM认证方式的现有系统要想非常稳定和完全的集成微软这些产品是手段是非常有限的,以前总是通过XMLHTTP模拟登陆方式去集成,但受客户端IE设置的一些限制而时常不太稳定,并且安全性非常低,所以彻底解决此类问题的方法也只有一个,就是实现WEB应用的WINDOWS集成验证方式。如果公司决定这样的模式才实现的话,必定涉及一个现有组织结构与AD帐户同步或对应的问题。
假如我们没有什么方法去处理的话,只能是辛苦系统维护的同事了,在AD和系统组织结构中分别建立帐户,一旦修改也在另一个地方修改。
其实问题并没有那么复杂,我们可以通过简单的WINDOWS服务代码来实现,屏蔽AD本身提供的维护界面,而在现有的组织结构中维护数据,然后通过windows服务程序的运行是实现AD帐户的新增和修改。
服务如图例:
实现的步骤如下:
1、首先初始化AD的数据,建立了一个OU和一个全局的用户组,然后在业务数据表中添加了两个字段:
[CreateADLog] [int] NULL , AD创建标记
[LastUpdateAD] [datetime] NULL AD修改标记
2、AD新增处理程序继承E8.Net异步架构服务处理类:IServiceDeal
/********************************************************************
* 描 述:具体实现类[AD同步帐户信息的异步更新、密码修改及帐户禁用]
* ****************************************************************/
using System;
using System.Data;
using System.Data.SqlClient;
using Epower.ADService.BaseDP;
using Epower.DevBase.BaseTools;
using System.Configuration;
using Epower.DevBase.BaseTools;
namespace Epower.ADServiceImpl
{
class ADCheckUpdateAndDisable: IServiceDeal
{
public ADCheckUpdateAndDisable()
{
}
string strSet = ""; //AD属性匹配列表
/// <summary>
/// 检查服务有效状态
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public override bool CheckServiceDo(DateTime dt)
{
return base.CheckServiceSubDo(dt, this.DealSetting);
}
/// <summary>
/// 设置服务属性
/// </summary>
/// <param name="t_interval"></param>
public override void SetServiceDealSet(int t_interval)
{
//执行接口的初试化动作
base.SetServiceDealSet(t_interval);
string sSet = System.Configuration.ConfigurationManager.AppSettings["ADCheckUpdateAndDisableSet"];
strSet = System.Configuration.ConfigurationManager.AppSettings["ADPropertieSet"];
base.DoSetServiceDealSet(sSet);
}
/// <summary>
/// 处理通知事件
/// </summary>
/// <param name="pNoticeDP"></param>
/// <param name="pXmlstr"></param>
/// <param name="sMsg"></param>
/// <returns></returns>
public override bool ServiceDeal(NoticeDP pNoticeDP, string pXmlstr, ref string sMsg)
{
bool ret = false;
SqlConnection cn = new SqlConnection();
//因为这个服务是按时间间隔来的,所以可以这么取
//构造需要通知的漂移时间段,间隔时间段上下半节/
//DateTime begindt = DateTime.Now.AddMilliseconds(this.DealSetting.Interval / 2 * -1);
//DateTime enddt = DateTime.Now.AddMilliseconds(this.DealSetting.Interval / 2);
//临时代码计数器
//TempAddLog();
try
{
cn = ConfigTool.GetConnection();
//每次仅创建10条,
string strSql = @"SELECT top 10 a.*,c.deptname
FROM ts_user a,ts_userdept b,ts_dept c
WHERE a.userid= b.userid and b.relation =0 and b.deptid = c.deptid
and a.createadlog = 1 and a.updatedate is not null and (a.updatedate > isnull(a.lastupdatead,getdate()) or a.lastupdatead is null)";
DataTable dt = SqlTool.ExecuteDataTable(cn, CommandType.Text, strSql);
DoUpdateADUser(dt);
ret = true;
}
catch (Exception e)
{
//返回错误信息
sMsg = e.Message;
}
finally
{
if (cn.State == ConnectionState.Open)
{
ConfigTool.CloseConnection(cn);
}
}
return ret;
}
/// <summary>
/// 修改AD用户
/// </summary>
/// <param name="dt"></param>
private void DoUpdateADUser(DataTable dt)
{
string strLoginName = "";
string strPersonName = "";
string strPassword = "";
string strUserID = "0";
int isDeleted = 0;
string strErrMsg = "";
foreach (DataRow dr in dt.Rows)
{
strUserID = dr["UserID"].ToString();
strLoginName = dr["loginName"].ToString();
strPersonName = dr["Name"].ToString();
strPassword = dr["Password"].ToString().Trim();
if (dr["deleted"] != null)
{
isDeleted = int.Parse(dr["deleted"].ToString());
}
//strErrMsg += " 删除状态 " + isDeleted.ToString(); ;
if (isDeleted == 0)
{
if (strPassword.Length > 0)
{
strPassword = EncryTool.DeCrypt(strPassword, "WangyqLijSuks_GainALotOfMoney_AndBuyCarAndBuildHouse");
}
try
{
System.DirectoryServices.DirectoryEntry de = ADTool.GetDirectoryEntry(strLoginName);
//de.Properties["Name"].Value = strPersonName;
//de.Properties["displayName"].Value = strPersonName;
//de.CommitChanges();
ADTool.SetPassword(de, strPassword);
de.CommitChanges();
//设置其它属性
UpdateOtherProperties(de, dr);
//更新创建状态
UpdateCreateLog(strUserID);
}
catch (Exception ee)
{
strErrMsg += " 同步用户" + strPersonName + "[" + strLoginName + "]相关属性时发生错误,错误描述为:" + ee.Message; ;
}
}
else
{
//禁用帐户
try
{
System.DirectoryServices.DirectoryEntry de = ADTool.GetDirectoryEntry(strLoginName);
ADTool.DisableUser(de);
de.CommitChanges();
//更新创建状态
UpdateCreateLog(strUserID);
}
catch (Exception ee)
{
strErrMsg += " 禁用帐户" + strPersonName + "[" + strLoginName + "]时发生错误,错误描述为:" + ee.Message; ;
}
}
}
if (strErrMsg.Length > 0)
{
throw new Exception(strErrMsg);
}
}
/// <summary>
/// 设置其它属性
/// </summary>
/// <param name="de"></param>
/// <param name="dr"></param>
private void UpdateOtherProperties(System.DirectoryServices.DirectoryEntry de, DataRow dr)
{
string[] sSets = strSet.Split(",".ToCharArray());
string sTemp = "";
try
{
foreach (string sSet in sSets)
{
string[] sItem = sSet.Split(":".ToCharArray());
if (sItem[0] != "password")
{
if (sItem[2] == "0")
{
//数据库中读取
//数据库中读取
//sTemp += sItem[1] + dr[sItem[1]].ToString() + " ::tel::" + dr["TelNo"].ToString();
if (dr.IsNull(sItem[1]))
{
sTemp = "";
}
else
{
sTemp = dr[sItem[1]].ToString();
}
if (sTemp.Length > 0)
{
ADTool.SetProperty(de, sItem[0], sTemp);
}
//ADTool.SetProperty(de, sItem[0], "aaaa");
}
else
{
//初值
ADTool.SetProperty(de, sItem[0], sItem[1]);
}
}
else
{
//创建用户时已经修改了密码
// ADTool.SetPassword(de, sItem[1]);
}
}
de.CommitChanges();
}
catch (Exception e)
{
throw e;
}
}
/// <summary>
/// 更新创建标记
/// </summary>
/// <param name="id"></param>
private void UpdateCreateLog(string id)
{
SqlConnection cn = new SqlConnection();
try
{
cn = ConfigTool.GetConnection();
string strSql = "update ts_user set lastupdatead = getdate() where userid =" + id;
SqlTool.ExecuteNonQuery(cn, CommandType.Text, strSql);
}
catch (Exception e)
{
//返回错误信息
throw e;
}
finally
{
if (cn.State == ConnectionState.Open)
{
ConfigTool.CloseConnection(cn);
}
}
}
/// <summary>
/// 临时记数器
/// </summary>
private void TempAddLog()
{
SqlConnection cn = new SqlConnection();
try
{
cn = ConfigTool.GetConnection();
string strSql = "update temp set idvalue = idvalue + 1 where id = 2";
SqlTool.ExecuteNonQuery(cn, CommandType.Text, strSql);
}
catch (Exception e)
{
//返回错误信息
throw e;
}
finally
{
if (cn.State == ConnectionState.Open)
{
ConfigTool.CloseConnection(cn);
}
}
}
}
}
3、在E8.Net异步架构中的app.Config文件中加如如下配置
<add key="ADCheckUpdateAndDisable" value="Epower.ADServiceImpl.ADCheckUpdateAndDisable,Epower.ADServiceImpl" />
</Channels>
<appSettings>
<add key="SQLConnString" value="server=deve;user id=sa;password=;database=epower;max pool size=100" />
<add key="TimerInterval" value="2000" />
<!-- AD同步设置 ADPropertieSet AD属性匹配列表 -->
<add key ="ADCheckAndUpdateSet" value ="SetType=10;PeriodType=10;BeginTime=08:00;EndTime=18:00;Interval=30000"/>
<add key ="ADCheckUpdateAndDisableSet" value ="SetType=10;PeriodType=10;BeginTime=09:00;EndTime=18:00;Interval=25000"/>
<add key ="DefaultOU" value =" xx物业总部"/>
<add key ="DefaultGroup" value ="xx物业"/>
<add key="ADPropertieSet" value="title:job:0,telephoneNumber:TelNo:0,department:deptname:0,company:xx物业公司:1,password:password:0" />
E8.Net异步服务程序就会加载 Epower.ADServiceImpl.ADCheckUpdateAndDisable,Epower.ADServiceImpl 程序集,并按照配置的运行计划进行执行了,从而实现 业务组织结构数据中的用户增加或删除同步到AD基础帐户数据中来,并创建了与帐户登录名相同的Exchange邮箱
5 使用C#编写 帐户更新同步的代码 继承E8.Net异步架构服务处理类: IServiceDeal
具体实现略
E8.Net工作流平台是基于微软.NET技术架构的工作流中间件产品,是国内商业流程管理(BPM)领域在.Net平台上的领先产品,是快速搭建流程管理解决方案的开发平台。
该软件采用面向服务的体系架构(SOA)和微软.NET技术,紧密集成微软各类应用服务器,并提供符合WfMC工作流标准的开发接口,提供应用开发框架(源码),支持异步服务和移动应用,可与ERP、微软SPS等实现企业应用集成(EAI)。
利用企业工作流引擎软件可以对各种管理流程进行建模、执行、监控和分析,实现流程管理(BPM)的电脑化和自动化;可以二次开发业务应用系统。
通过实施企业工作流引擎软件,可以掌握企业流程的运行绩效和运行成本情况,为企业实施流程重组(BPR)提供科学依据。利用信息技术辅助企业实施流程管理和流程重组工作,利用e化手段推进企业精细化管理和KPI关键指标体系的建设,提升企业战略执行力。
流程管理是企业管理的基石.