// 修改用户密码。这是指用户修改自己帐户的密码,需提供旧密码 // return: // -1 error // 0 succeed public int ChangeUserPassword( string strLibraryCodeList, string strUserName, string strOldPassword, string strNewPassword, out string strError) { strError = ""; int nRet = 0; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return(-1); } this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 XmlNode node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (node == null) { strError = "用户 '" + strUserName + "' 不存在"; return(-1); } string strExistLibraryCodeList = DomUtil.GetAttr(node, "libraryCode"); // 2012/9/9 // 分馆用户只允许修改馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(strExistLibraryCodeList) == true || IsListInList(strExistLibraryCodeList, strLibraryCodeList) == false) { strError = "当前用户只能修改图书馆代码完全完全属于 '" + strLibraryCodeList + "' 范围的用户的密码"; return(-1); } } // 验证旧密码 #if NO // 以前的做法 string strExistPassword = DomUtil.GetAttr(node, "password"); if (String.IsNullOrEmpty(strExistPassword) == false) { try { strExistPassword = Cryptography.Decrypt(strExistPassword, EncryptKey); } catch { strError = "已经存在的(加密后)密码格式不正确"; return(-1); } } if (strExistPassword != strOldPassword) { strError = "所提供的旧密码经验证不匹配"; return(-1); } #endif string strExistPassword = DomUtil.GetAttr(node, "password"); nRet = LibraryServerUtil.MatchUserPassword(strOldPassword, strExistPassword, out strError); if (nRet == -1) { return(-1); } if (nRet == 0) { strError = "所提供的旧密码经验证不匹配"; return(-1); } // 设置新密码 #if NO // 以前的做法 strNewPassword = Cryptography.Encrypt(strNewPassword, EncryptKey); DomUtil.SetAttr(node, "password", strNewPassword); #endif string strHashed = ""; nRet = LibraryServerUtil.SetUserPassword(strNewPassword, out strHashed, out strError); if (nRet == -1) { return(-1); } DomUtil.SetAttr(node, "password", strHashed); this.Changed = true; return(0); } finally { this.m_lock.ReleaseWriterLock(); } // return 0; }
// 创建新用户 // TODO: 对DOM加锁 public int CreateUser( string strLibraryCodeList, string strUserName, string strOperator, UserInfo userinfo, string strClientAddress, out string strError) { strError = ""; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return(-1); } if (strUserName != userinfo.UserName) { strError = "strUserName参数值和userinfo.UserName不一致"; return(-1); } // 2012/9/9 // 分馆用户只允许创建馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(userinfo.LibraryCode) == true || IsListInList(userinfo.LibraryCode, strLibraryCodeList) == false) { strError = "当前用户只能创建图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的新用户"; return(-1); } } int nResultValue = -1; // 检查名字空间。 // return: // -2 not found script // -1 出错 // 0 成功 int nRet = this.DoVerifyBarcodeScriptFunction( null, "", strUserName, out nResultValue, out strError); if (nRet == -2) { // 没有校验条码号功能,所以无法校验用户名和条码号名字空间的冲突 goto SKIP_VERIFY; } if (nRet == -1) { strError = "校验用户名 '" + strUserName + "' 和条码号潜在冲突过程中(调用函数DoVerifyBarcodeScriptFunction()时)发生错误: " + strError; return(-1); } Debug.Assert(nRet == 0, ""); if (nResultValue == -1) { strError = "校验用户名 '" + strUserName + "' 和条码号潜在冲突过程中发生错误: " + strError; return(-1); } if (nResultValue == 1) { strError = "名字 '" + strUserName + "' 和条码号名字空间发生冲突,不能作为用户名。"; return(-1); } SKIP_VERIFY: XmlNode nodeAccount = null; this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 nodeAccount = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (nodeAccount != null) { strError = "用户 '" + strUserName + "' 已经存在"; return(-1); } XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("accounts"); if (root == null) { root = this.LibraryCfgDom.CreateElement("accounts"); this.LibraryCfgDom.DocumentElement.AppendChild(root); } nodeAccount = this.LibraryCfgDom.CreateElement("account"); root.AppendChild(nodeAccount); DomUtil.SetAttr(nodeAccount, "name", userinfo.UserName); if (String.IsNullOrEmpty(userinfo.Type) == false) { DomUtil.SetAttr(nodeAccount, "type", userinfo.Type); } DomUtil.SetAttr(nodeAccount, "rights", userinfo.Rights); DomUtil.SetAttr(nodeAccount, "libraryCode", userinfo.LibraryCode); DomUtil.SetAttr(nodeAccount, "access", userinfo.Access); DomUtil.SetAttr(nodeAccount, "comment", userinfo.Comment); // 设置密码 if (userinfo.SetPassword == true) { #if NO // 以前的做法 string strPassword = Cryptography.Encrypt(userinfo.Password, EncryptKey); DomUtil.SetAttr(nodeAccount, "password", strPassword); #endif string strHashed = ""; nRet = LibraryServerUtil.SetUserPassword(userinfo.Password, out strHashed, out strError); if (nRet == -1) { return(-1); } DomUtil.SetAttr(nodeAccount, "password", strHashed); } this.Changed = true; // 2014/9/16 if (userinfo.UserName == "reader") { this.ClearLoginCache(""); } } finally { this.m_lock.ReleaseWriterLock(); } // 写入日志 { XmlDocument domOperLog = PrepareOperlogDom("new", strOperator); XmlNode node = domOperLog.CreateElement("account"); domOperLog.DocumentElement.AppendChild(node); DomUtil.SetElementOuterXml(node, nodeAccount.OuterXml); // 写入日志 nRet = this.OperLog.WriteOperLog(domOperLog, strClientAddress, out strError); if (nRet == -1) { strError = "SetUser() API 写入日志时发生错误: " + strError; return(-1); } } return(0); }
// 强制修改用户密码。不修改其他信息。 public int ResetUserPassword( string strLibraryCodeList, string strUserName, string strOperator, string strNewPassword, string strClientAddress, out string strError) { strError = ""; int nRet = 0; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return(-1); } XmlNode nodeAccount = null; string strHashedPassword = ""; this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 nodeAccount = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (nodeAccount == null) { strError = "用户 '" + strUserName + "' 不存在"; return(-1); } string strExistLibraryCodeList = DomUtil.GetAttr(nodeAccount, "libraryCode"); // 2012/9/9 // 分馆用户只允许修改馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(strExistLibraryCodeList) == true || IsListInList(strExistLibraryCodeList, strLibraryCodeList) == false) { strError = "当前用户只能重设 图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的用户的密码"; return(-1); } } // 强制修改密码。无需验证旧密码 #if NO // 以前的做法 strHashedPassword = Cryptography.Encrypt(strNewPassword, EncryptKey); DomUtil.SetAttr(nodeAccount, "password", strHashedPassword); #endif nRet = LibraryServerUtil.SetUserPassword(strNewPassword, out strHashedPassword, out strError); if (nRet == -1) { return(-1); } DomUtil.SetAttr(nodeAccount, "password", strHashedPassword); this.Changed = true; } finally { this.m_lock.ReleaseWriterLock(); } { XmlDocument domOperLog = PrepareOperlogDom("resetpassword", strOperator); // 2015/10/17 新增加的元素。此前缺这个元素。建议日志恢复的时候,忽略没有 userName 元素的日志记录 DomUtil.SetElementText(domOperLog.DocumentElement, "userName", strUserName); #if NO XmlNode node = domOperLog.CreateElement("newPassword"); domOperLog.DocumentElement.AppendChild(node); node.InnerText = strHashedPassword; #endif DomUtil.SetElementText(domOperLog.DocumentElement, "newPassword", strHashedPassword); // 写入日志 nRet = this.OperLog.WriteOperLog(domOperLog, strClientAddress, out strError); if (nRet == -1) { strError = "SetUser() API 写入日志时发生错误: " + strError; return(-1); } } return(0); }
// 修改用户 public int ChangeUser( string strLibraryCodeList, string strUserName, string strOperator, UserInfo userinfo, string strClientAddress, out string strError) { strError = ""; int nRet = 0; if (String.IsNullOrEmpty(strUserName) == true) { strError = "strUserName参数值不能为空"; return(-1); } if (strUserName != userinfo.UserName) { strError = "strUserName参数值和userinfo.UserName不一致"; return(-1); } XmlNode nodeAccount = null; string strOldOuterXml = ""; this.m_lock.AcquireWriterLock(m_nLockTimeout); try { // 查重 nodeAccount = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//accounts/account[@name='" + strUserName + "']"); if (nodeAccount == null) { strError = "用户 '" + strUserName + "' 不存在"; return(-1); } strOldOuterXml = nodeAccount.OuterXml; string strExistLibraryCodeList = DomUtil.GetAttr(nodeAccount, "libraryCode"); // 2012/9/9 // 分馆用户只允许修改馆代码属于管辖分馆的帐户 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(strExistLibraryCodeList) == true || IsListInList(strExistLibraryCodeList, strLibraryCodeList) == false) { strError = "当前用户只能修改图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的用户信息"; return(-1); } } // 2012/9/9 // 分馆用户只允许将帐户的馆代码修改到指定范围内 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { if (string.IsNullOrEmpty(userinfo.LibraryCode) == true || IsListInList(userinfo.LibraryCode, strLibraryCodeList) == false) { strError = "当前用户只能将用户信息的馆代码修改到完全属于 '" + strLibraryCodeList + "' 范围内的值"; return(-1); } } DomUtil.SetAttr(nodeAccount, "name", userinfo.UserName); DomUtil.SetAttr(nodeAccount, "type", userinfo.Type); DomUtil.SetAttr(nodeAccount, "rights", userinfo.Rights); DomUtil.SetAttr(nodeAccount, "libraryCode", userinfo.LibraryCode); DomUtil.SetAttr(nodeAccount, "access", userinfo.Access); DomUtil.SetAttr(nodeAccount, "comment", userinfo.Comment); // 强制修改密码。无需验证旧密码 if (userinfo.SetPassword == true) { #if NO // 以前的做法 string strPassword = Cryptography.Encrypt(userinfo.Password, EncryptKey); DomUtil.SetAttr(nodeAccount, "password", strPassword); #endif string strHashed = ""; nRet = LibraryServerUtil.SetUserPassword(userinfo.Password, out strHashed, out strError); if (nRet == -1) { return(-1); } DomUtil.SetAttr(nodeAccount, "password", strHashed); } this.Changed = true; // 2014/9/16 if (userinfo.UserName == "reader") { this.ClearLoginCache(""); } } finally { this.m_lock.ReleaseWriterLock(); } // 写入日志 { XmlDocument domOperLog = PrepareOperlogDom("change", strOperator); if (string.IsNullOrEmpty(strOldOuterXml) == false) { XmlNode node_old = domOperLog.CreateElement("oldAccount"); domOperLog.DocumentElement.AppendChild(node_old); node_old = DomUtil.SetElementOuterXml(node_old, strOldOuterXml); DomUtil.RenameNode(node_old, null, "oldAccount"); } XmlNode node = domOperLog.CreateElement("account"); domOperLog.DocumentElement.AppendChild(node); DomUtil.SetElementOuterXml(node, nodeAccount.OuterXml); // 写入日志 nRet = this.OperLog.WriteOperLog(domOperLog, strClientAddress, out strError); if (nRet == -1) { strError = "SetUser() API 写入日志时发生错误: " + strError; return(-1); } } return(0); }
// 从注册表和 library.xml 文件中获得实例信息 // parameters: // // return: // -1 出错 // 0 实例没有找到 // 1 成功 public static int GetLibraryInstanceInfo( string strInstanceNameParam, out LibraryInstanceInfo info, out string strError) { strError = ""; info = new LibraryInstanceInfo(); string strInstanceName = ""; string strDataDir = ""; string strCertificatSN = ""; string[] existing_urls = null; for (int i = 0; ; i++) { bool bRet = InstallHelper.GetInstanceInfo("dp2Library", i, out strInstanceName, out strDataDir, out existing_urls, out strCertificatSN); if (bRet == false) { strError = "实例 '" + strInstanceNameParam + "' 不存在"; return(0); } if (strInstanceName == strInstanceNameParam) { info.InstanceName = strInstanceName; info.Urls = existing_urls; info.DataDir = strDataDir; break; } } string strFileName = Path.Combine(strDataDir, "library.xml"); if (File.Exists(strFileName) == false) { strError = "实例 '" + strInstanceNameParam + "' 的 library.xml 文件不存在"; return(0); } XmlDocument dom = new XmlDocument(); try { dom.Load(strFileName); } catch (Exception ex) { strError = "文件 '" + strFileName + "' 装载到 XMLDOM 时出错: " + ex.Message; return(-1); } if (dom.DocumentElement == null) { strError = "文件 '" + strFileName + "' 格式不正确,缺乏根元素"; return(-1); } info.Version = LibraryServerUtil.GetLibraryXmlVersion(dom); // supervisor // XmlElement nodeSupervisor = dom.DocumentElement.SelectSingleNode("accounts/account[@type='']") as XmlElement; XmlElement nodeSupervisor = null; // 找到第一个具备 managedatabase 权限用户 XmlNodeList nodes = dom.DocumentElement.SelectNodes("accounts/account[@type='']"); if (nodes.Count > 0) { foreach (XmlElement account in nodes) { string strRights = account.GetAttribute("rights"); if (StringUtil.IsInList("managedatabase", strRights) == true) { nodeSupervisor = account; break; } } } if (nodeSupervisor != null) { info.SupervisorUserName = nodeSupervisor.GetAttribute("name"); info.SupervisorPassword = nodeSupervisor.GetAttribute("password"); if (info.Version <= 2.0) { // library.xml 2.00 及以前的做法 try { info.SupervisorPassword = Cryptography.Decrypt(info.SupervisorPassword, "dp2circulationpassword"); } catch { strError = "<account password='******' /> 中的密码不正确"; return(-1); } // 得到 supervisor 密码的明文 } } string strValue = dom.DocumentElement.GetAttribute("_initialDatabase"); if (DomUtil.IsBooleanTrue(strValue, false) == true) { info.InitialDatabase = true; } else { info.InitialDatabase = false; } return(1); }
// 要求操作者用 supervisor 账号登录一次。以便后续进行各种重要操作。 // 只需要 library.xml 即可,不需要 dp2library 在运行中。 // return: // -2 实例没有找到 // -1 出错 // 0 放弃验证 // 1 成功 public static int LibrarySupervisorLogin(IWin32Window owner, string strInstanceName, string strComment, out string strError) { strError = ""; LibraryInstanceInfo info = null; // return: // -1 出错 // 0 实例没有找到 // 1 成功 int nRet = GetLibraryInstanceInfo( strInstanceName, out info, out strError); if (nRet == -1) { return(-1); } if (nRet == 0) { strError = "实例 '" + strInstanceName + "' 没有找到"; return(-2); } if (string.IsNullOrEmpty(info.SupervisorUserName) == true) { // TODO: 此时是否可以不用验证了呢? strError = "实例 '" + strInstanceName + "' 的账户中,没有找到具有 managedatabase 权限的管理员账户,因此无法验证操作者身份"; return(-1); } ConfirmSupervisorDialog dlg = new ConfirmSupervisorDialog(); GuiUtil.AutoSetDefaultFont(dlg); dlg.Comment = strComment; dlg.ServerUrl = "实例 '" + strInstanceName + "'"; dlg.UserName = info.SupervisorUserName; dlg.StartPosition = FormStartPosition.CenterScreen; REDO_LOGIN: dlg.ShowDialog(owner); if (dlg.DialogResult == DialogResult.Cancel) { return(0); } if (info.Version <= 2.0) { // 以前的做法 if (dlg.Password != info.SupervisorPassword) { MessageBox.Show(owner, "密码不正确。请重新输入密码"); goto REDO_LOGIN; } } else { // 新的做法 nRet = LibraryServerUtil.MatchUserPassword(dlg.Password, info.SupervisorPassword, out strError); if (nRet == -1) { strError = "MatchUserPassword() error: " + strError; return(-1); } Debug.Assert(nRet == 0 || nRet == 1, ""); if (nRet == 1) { MessageBox.Show(owner, "密码不正确。请重新输入密码"); goto REDO_LOGIN; } } return(1); }