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

目录

权限管理系统系列之序言  

权限管理系统系列之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把所有的密码都泄露出来了,好像那时还是明文的,这好像还是去年的事情吧!

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

原文地址:https://www.cnblogs.com/luoyuhao/p/4179005.html