• 权限管理系统系列之登录、升级模块


    目录

    权限管理系统系列之序言  

    权限管理系统系列之WCF通信

           之前写了两篇关于权限管理系统的博客了,由于这段时间有事比较忙就暂停了,今天继续编写权限管理系统之登陆和升级模块,登陆和升级也是每个系统之必须的模块,对于一个Winform程序,在登陆之前必须要先进行程序的升级,所以先介绍升级模块。

    升级模块

    表结构如下:

     插入数据表数据如下:

           一般程序升级可能有好几种,比如说有根本版本号比较升级、根据DLL生成时间比较等等,而我介绍的是根据版本号进行升级。我们需要在服务端将DLL文件的 版本写入到数据表中,这样供每个客户端去比较版本号,就是每次打开客户端之前进行检测版本号,如果版本号相等则不升级,如果不相等则进行升级操作。

    服务端实现逻辑如下:

     1         /// <summary>
     2         /// 更新客户端程序集信息
     3         /// </summary>
     4         public static void UpdateAssembleInfo()
     5         {
     6             DbHelper dbhelper = new DbHelper(AppServer.dbName);
     7             string sql = "select * from t_fw_assemble_list t";
     8             DataTable dt = dbhelper.Query(sql);
     9             DirectoryInfo dirInfo = new DirectoryInfo(Application.StartupPath);
    10             FileVersionInfo fvi = null;
    11             string updateSql = "update t_fw_assemble_list set s_versionno= '{0}',t_timestamp=getdate()  where s_type='{1}' and s_filename='{2}'";
    12             string fName = string.Empty;
    13             GetAllFiles(dirInfo);
    14             bool isAddLog = true;
    15             StreamReader sr = null;
    16             for (int i = 0; i < dt.Rows.Count; i++)
    17             {
    18                 fName = dt.Rows[i]["S_FILENAME"].ToString();
    19                 if (fileNameDic.ContainsKey(fName))
    20                 {
    21                     if (dt.Rows[i]["L_UPDATE"].ToString() == "2")
    22                     {
    23                         sr = new StreamReader(Application.StartupPath + "\" + fName);
    24                         string fileContext = sr.ReadToEnd();
    25                         sr.Close();
    26                         sr.Dispose();
    27                         sql = string.Format(updateSql, Common.Util.MD5Encrypt.MD5EncryptDES(fileContext), dt.Rows[i]["S_TYPE"], fName);
    28                         dbhelper.ExecuteSql(sql);
    29                         isAddLog = false;
    30                     }
    31                     else
    32                     {
    33                         fvi = FileVersionInfo.GetVersionInfo(fileNameDic[fName]);
    34                         if (!dt.Rows[i]["S_VERSIONNO"].ToString().Equals(fvi.FileVersion))
    35                         {
    36                             sql = string.Format(updateSql, fvi.FileVersion, dt.Rows[i]["S_TYPE"], fName);
    37                             dbhelper.ExecuteSql(sql);
    38                             isAddLog = false;
    39                         }
    40                     }
    41                     if (!isAddLog)
    42                     {
    43                         isAddLog = AddLog();
    44                     }
    45                 }
    46             }
    47         }

    以上代码主要是写入版本到数据库里,每次服务端启动首先执行这段代码。

    服务端搞定我就来看看客户端了,客户端启动时调用以下方法实现:

     1                 bool isDownLoad = false;
     2                 if (args != null)
     3                 {
     4                     if (args.Length > 0)
     5                     {
     6                         for (int i = 0; i < args.Length; i++)
     7                         {
     8                             if (args[i] == "Update")
     9                             {
    10                                 isDownLoad = true;
    11                                 break;
    12                             }
    13                         }
    14                     }
    15                 }
    16                 if (isDownLoad)
    17                 {
    18                     //启动主界面
    19                     Application.Run(new LoginForm());
    20                 }
    21                 else
    22                 {
    23                     //更新客户端程序集
    24                     if (UpdateAssembleData.UpdateAssembleInfo() > 0)
    25                     {
    26                         DownLoadForm dlf = new DownLoadForm();
    27                         dlf.fileNameList = UpdateAssembleData.fileNameList;
    28                         //启动下载程序界面
    29                         Application.Run(dlf);
    30                     }
    31                     else
    32                     {
    33                         //启动主界面
    34                         Application.Run(new LoginForm());
    35                     }
    36                 }

    更新时会弹出升级窗体,上面会显示升级的DLL文件,以及文件升级的进度条,升级完成启动新的程序,升级过程的核心代码:

      1         /// <summary>
      2         /// 下载文件
      3         /// </summary>
      4         private void DownLoadFile()
      5         {
      6             if (fileNameList.Count > 0)
      7             {
      8                 //CallService service = new CallService("GetFile");
      9                 int countLen = fileNameList.Count;
     10                 this.pbarDownLoad.Position = this.pbarDownLoad.Properties.Minimum;
     11                 double step = this.pbarDownLoad.Properties.Maximum / countLen;
     12                 string fName = string.Empty;
     13                 string upPath = Application.StartupPath + "\Update\";
     14                 if (!Directory.Exists(upPath))
     15                 {
     16                     Directory.CreateDirectory(upPath);
     17                 }
     18 
     19                 string sql = string.Empty;
     20                 FileStream fs;
     21                 bool isStartUpdate = false;
     22                 List<string> list = new List<string>();
     23                 List<string> getList = new List<string>();
     24                 //int fLen = 0;
     25                 long pageNum = 0;
     26                 for (int i = 0; i < countLen; i++)
     27                 {
     28                     bool isFirstPBLen = true;
     29                     isStartUpdate = false;
     30                     fName = fileNameList[i];
     31                     IAsyncResult iart = this.lblDownLoad.BeginInvoke(new SetLabelText(AsyncLabel), new object[] { "正在下载文件 " + fName });
     32                     this.lblDownLoad.EndInvoke(iart);
     33                     pageNum = 1;
     34                     list.Clear();
     35                     list.Add(fName);
     36                     list.Add(pageNum.ToString ());
     37                     
     38                     //创建服务器下载的文件
     39                     string tmpPath = upPath + fName;
     40                     tmpPath = tmpPath.Substring(0, tmpPath.LastIndexOf('\'));
     41                     if (!Directory .Exists (tmpPath))
     42                     {
     43                         Directory.CreateDirectory(tmpPath);
     44                     }
     45                     fs = new FileStream(upPath + fName, FileMode.Create, FileAccess.Write);
     46 
     47                     while (true)
     48                     {
     49                         Result result = FileData.DoGetFile(list);
     50                         if (!result.success)//DoGetFile
     51                         {
     52                             Comm.WriteLogAndShowMessageBox.Error(result.msg, "Client.Win.DownLoadForm.DownLoadFile()出错:" + result.msg);
     53                             StartUpdateApp(isStartUpdate);
     54                             break;
     55                         }
     56                         else
     57                         {
     58                             getList = JSON.Json2Object<List<string>>(result.data); //service.GetResult<List<string>>();
     59                             byte[] buffer = Convert.FromBase64String(getList[2]);
     60 
     61                             if (isFirstPBLen)
     62                             {
     63                                 //初始化当前文件进度条
     64                                 iart = this.pbarCurrDownLoad.BeginInvoke(new UpdateProcessBar(AsyncIni), new object[] { Convert.ToInt32 (getList[0]), this.pbarCurrDownLoad });
     65                                 this.pbarCurrDownLoad.EndInvoke(iart);
     66                                 isFirstPBLen = false;
     67                                 Thread.Sleep(100);
     68                             }
     69                             
     70                             //接收服务器返回的二制数据
     71                             fs.Write(buffer, 0, buffer.Length);
     72                             pageNum ++;
     73                             list[1] = pageNum.ToString();
     74                             AsyncProcessBar(this.pbarCurrDownLoad, 1);
     75                             if (buffer.Length < Convert.ToInt32(getList[1]))
     76                             {
     77                                 break;
     78                             }
     79                             
     80                         }
     81                     }
     82                     fs.Flush();
     83                     fs.Close();
     84                     //插入日志记录到服务器
     85 
     86                     Tools.WriteOptLogToDb(Tools.OPType.Update, "", fName, "从服务器更新文件" + fName);
     87                     //刷新进度条
     88                     if (this.pbarDownLoad.Position < this.pbarDownLoad.Properties.Maximum)
     89                     {
     90                         if (i == countLen - 1)
     91                         {
     92                             AsyncProcessBar(this.pbarDownLoad, step + 1);
     93                         }
     94                         else
     95                         {
     96                             AsyncProcessBar(this.pbarDownLoad, step);
     97                         }
     98                     }
     99                     isStartUpdate = true;
    100                 }
    101                 StartUpdateApp(isStartUpdate);
    102             }
    103         }

    启动本地程序:

     1         /// <summary>
     2         /// 启动更新程序并退出本程序
     3         /// </summary>
     4         private void StartUpdateApp(bool isStartUpdate)
     5         {
     6             if (isStartUpdate)
     7             {
     8                 string filePath = Application.StartupPath + "\Update\Update.exe";
     9                 if (File.Exists (filePath))
    10                 {
    11                     File.Copy(filePath, Application.StartupPath + "\Update.exe" , true);
    12                     File.Delete(filePath);
    13                 }
    14 
    15                 Process.Start(Application.StartupPath + "\Update.exe");
    16             }
    17             //Environment.Exit(0);
    18             Application.Exit();
    19             Process.GetCurrentProcess().Kill();
    20         }

    以上基本上可以实现对程序的升级了。O(∩_∩)O哈哈~

    登陆模块

    用户表结构:

     升级完成后就该启动登陆模块。登陆界面如下:

    相对而言登陆界面就超级简单了,用户名和密码两个文本框,两个按钮一个是登陆和一个取消按钮,最下面显示版权。

      1         #region 按钮
      2         //登录
      3         private void logButton_Click(object sender, EventArgs e)
      4         {
      5             if (locked)
      6             {
      7                 #region 解锁
      8                 try
      9                 {
     10                     if (pswTextBox.Text == context.Password)
     11                     {
     12                         this.Hide();
     13                         context.ParentForm.Enabled = true;
     14                         context.ParentForm.Show();
     15                         Form[] childrens = context.ParentForm.OwnedForms;
     16                         if (childrens != null)
     17                         {
     18                             foreach (Form item in childrens)
     19                             {
     20                                 if (item.IsDisposed)
     21                                     continue;
     22                                 if (!item.IsMdiChild && !"系统已锁定".Equals(item.Text))
     23                                 {
     24                                     item.Show();
     25                                 }
     26                             }
     27                         }
     28                         context.ParentForm.Activate();
     29                         this.DialogResult = DialogResult.OK;
     30                     }
     31                     else
     32                     {
     33                         Comm.MessageBox.Info("密码错误!");
     34                         pswTextBox.Text = ""; ;
     35                         pswTextBox.Focus();
     36                         return;
     37                     }
     38                 }
     39                 catch (Exception exMsg)
     40                 {
     41                     WriteLogAndShowMessageBox.Error("解锁出错:" + exMsg.Message, "解锁出错:" + exMsg.ToString());
     42                     pswTextBox.Text = ""; ;
     43                     pswTextBox.Focus();
     44                 }
     45                 #endregion 解锁
     46             }
     47             else
     48             {
     49                 #region 登录
     50                 try
     51                 {
     52                     if (string.IsNullOrWhiteSpace(nameTextBox.Text))
     53                     {
     54                         Comm.MessageBox.Info("请输入账号");
     55                         nameTextBox.Focus();
     56                         return;
     57                     }
     58                     if (string.IsNullOrWhiteSpace(pswTextBox.Text))
     59                     {
     60                         Comm.MessageBox.Info("请输入密码");
     61                         pswTextBox.Focus();
     62                         return;
     63                     }
     64                     string name = nameTextBox.Text;
     65                     string password = pswTextBox.Text;
     66                     string despsw = Encrypt.EncryptDES(password, Const.EncryptKey);
     67 
     68                     Result result = LoginData.Login(name, despsw);
     69                     if (!result.success)
     70                     {
     71                         Comm.MessageBox.Info(result.msg);
     72                         if (result.msg.Contains("账号不存在"))
     73                         {
     74                             nameTextBox.Text = "";
     75                             nameTextBox.Focus();
     76                         }
     77                         else if (result.msg.Contains("密码错误"))
     78                         {
     79                             pswTextBox.Text = "";
     80                             pswTextBox.Focus();
     81                         }
     82                         else
     83                         {
     84                             nameTextBox.Text = "";
     85                             pswTextBox.Text = "";
     86                             nameTextBox.Focus();
     87                         }
     88                         return;
     89                     }
     90                     else
     91                     {
     92                         t_fw_user user = new t_fw_user();
     93                         user.s_usercode = name;
     94                         user.s_password = password;
     95                         string resData = JSON.Json2Object<string>(result.data);
     96                         user.s_username = resData;
     97                         //user.Mode = int.Parse(resData[1]);
     98                         //user.UserCode2 = resData[2];
     99                         this.Hide();
    100                         MainForm mainform = new MainForm(user);
    101                         mainform.Show();
    102                         mainform.Text = systemName;
    103                         nameTextBox.Text = "";
    104                         pswTextBox.Text = "";
    105                         Log.Info(name + " 用户登录成功!");
    106                         Tools.WriteOptLogToDb(Tools.OPType.Login, "", "用户:" + name + "登录", "用户登录");
    107                     }
    108                 }
    109                 catch (Exception exMsg)
    110                 {
    111                     WriteLogAndShowMessageBox.Error("登录出错:" + exMsg.Message, "登录出错:" + exMsg.ToString());
    112                     nameTextBox.Text = "";
    113                     pswTextBox.Text = "";
    114                     nameTextBox.Focus();
    115                 }
    116                 #endregion 登录
    117             }
    118         }

    以上即可实现用户的登陆,密码采用DES加密,DES加密和解密方法如下:

     1     /// <summary>
     2     /// Description of Encrypt.
     3     /// </summary>
     4     public static class Encrypt
     5     {
     6         //默认密钥向量
     7         private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
     8         /// <summary>
     9         /// DES加密字符串
    10         /// </summary>
    11         /// <param name="encryptString">待加密的字符串</param>
    12         /// <param name="encryptKey">加密密钥,要求为8位</param>
    13         /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
    14         public static string EncryptDES(string encryptString, string encryptKey)
    15         {
    16             if (!string.IsNullOrEmpty(encryptString))
    17             {
    18                 try
    19                 {
    20                     byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
    21                     byte[] rgbIV = Keys;
    22                     byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
    23                     DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
    24                     MemoryStream mStream = new MemoryStream();
    25                     CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
    26                     cStream.Write(inputByteArray, 0, inputByteArray.Length);
    27                     cStream.FlushFinalBlock();
    28                     return Convert.ToBase64String(mStream.ToArray());
    29                 }
    30                 catch
    31                 {
    32                     return encryptString;
    33                 }
    34             }
    35             else
    36             {
    37                 return string.Empty;
    38             }
    39         }
    40         
    41         /// <summary>
    42         /// DES解密字符串
    43         /// </summary>
    44         /// <param name="decryptString">待解密的字符串</param>
    45         /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
    46         /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
    47         public static string DecryptDES(string decryptString, string decryptKey)
    48         {
    49             try
    50             {
    51                 byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
    52                 byte[] rgbIV = Keys;
    53                 byte[] inputByteArray = Convert.FromBase64String(decryptString);
    54                 DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
    55                 MemoryStream mStream = new MemoryStream();
    56                 CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
    57                 cStream.Write(inputByteArray, 0, inputByteArray.Length);
    58                 cStream.FlushFinalBlock();
    59                 return Encoding.UTF8.GetString(mStream.ToArray());
    60             }
    61             catch
    62             {
    63                 return decryptString;
    64             }
    65         }
    66     }

    现在应该所有的程序密码都进行了加密了吧!之前好像CSDN把所有的密码都泄露出来了,好像那时还是明文的,这好像还是去年的事情吧!

    以上简单介绍了升级和登陆模块,也许做好这块的功能是一个项目起到至关重要的作用。

  • 相关阅读:
    Hibernate---对象的三种状态
    grunt+bower依赖管理
    grunt 的安装和简单使用
    sqlserver dmv 动态管理视图
    ado.net 数据库连接池
    桥接模式
    .net MVP
    主定理(分治算法)
    图中环的判断
    选举协议paxos 协议 理解
  • 原文地址:https://www.cnblogs.com/luoyuhao/p/4179005.html
Copyright © 2020-2023  润新知