用C#和winform实现界面版访问控制(基于MySQL5.7数据库)

实验开发环境

开发工具:Visual studio 2019
操作系统:windows 10 家庭版
语言:C#
界面设计:winfrom窗体应用程序

实验原理

1969年,B.W.Lampson通过形式化表示方法运用主体、客体和访问控制矩阵的思想第一次对访问控制问题进行了抽象。主体是访问操作中的主动实体,客体是访问操作中的被动实体,主体对客体进行访问,系统使用引用监控器根据访问矩阵来进行访问控制。
它由三元组(S,O,A)来定义,其中:
S是主体的集合——行标对应主体
O是客体的集合——列标对应客体
A是访问矩阵,矩阵元素A[s,o]是主体s在o上实施的操作
客体以及在其上实施的操作类型取决应用系统本身的特点。
本实验中:1代表有访问权限;0代表无访问权限

实验步骤和内容

1、 完成对原理的理解和应用
2、 设计过程, 画流程图
3、 用winform进行界面设计
4、 添加控件,完成各个部分代码
5、 实现功能,调试,美化

成品效果

客户端的界面管理员端的界面(初学C#和winform,做的很生涩,还望大佬勿喷)

代码实现

客户端+管理员端+MySQL5.7数据库
登录功能实现,并将用户的密码进行一次MD5运算后存入数据库
管理员端没有设置登录等功能,打开即管理(其实是多余的功能不想写~)

//客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;   //引用MySql,记得引用库
using System.Security.Cryptography; //用于MD5加密

namespace 访问控制
{
    public partial class client : Form
    {
        public client()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 注册按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnRegister_Click(object sender, EventArgs e)
        {
            try
            {


                if (username.Text == "" || password.Text == "")//判空
                {
                    MessageBox.Show("用户名或密码不能为空!", "提示");
                }
                else//打开数据库插入用户名和密码
                {
                    string username = this.username.Text.Trim();//暂时备份用户名和密码
                    string password = this.password.Text.Trim();
                    string Enc = Md5(password);//md5加密密码

                    //首先检查用户是否已经被注册
                    string constructorString = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
                    MySqlConnection myConnnect = new MySqlConnection(constructorString);
                    myConnnect.Open();//打开数据库

                    MySqlCommand myCmd = new MySqlCommand("SELECT times from user_table where username='" + username + "' and password='" + Enc/*password*/ + "'; ", myConnnect);//看select语句是否执行
                    MySqlDataReader dataReader = myCmd.ExecuteReader();//如存在times的,将会存在dataReader[0]中
                    if (dataReader.HasRows)
                    {
                        MessageBox.Show("该用户已被注册!","提示");
                    }
                    else
                    {
                        myConnnect.Close();//关闭上一个dataReader

                        string constructorString2 = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
                        MySqlConnection myConnnect2 = new MySqlConnection(constructorString2);
                        myConnnect2.Open();//打开数据库

                        //插入用户名和密码到user_table表-----密码未加密
                        MySqlCommand myCmd2 = new MySqlCommand($"INSERT INTO user_table(username,password) VALUES('{username}','{Enc/*password*/}');", myConnnect2);
                        //插入用户名到resources表---数据库默认权限是0
                        MySqlCommand myCmd3 = new MySqlCommand($"INSERT INTO resources(username) VALUES('{username}');", myConnnect2);

                        if (myCmd2.ExecuteNonQuery() > 0 && myCmd3.ExecuteNonQuery() > 0)//用and(&&),两句同时满足才算插入成功
                                                                                         //ExecuteNonQuery()返回影响的行数(用于insert,update,delete),其他关键字返回-1
                        {
                            MessageBox.Show("注册成功!插入数据库成功!","提示");//插入数据库成功!
                        }
                        myConnnect2.Close();//及时关闭数据库连接

                    }

                }
            }
            catch (Exception ex) //异常时执行下面语句
            {
                MessageBox.Show("运行出现错误!","提示");
                //TextBox.AppendText("运行出现错误!" + "\r\n");
            }
        }


        string Username;
        string EnPwd;

        /// <summary>
        /// 登录按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnLogin_Click(object sender, EventArgs e)
        {
            try
            {
                if (username.Text == "" || password.Text == "")//判空
                {
                    MessageBox.Show("用户名或密码不能为空!", "提示");
                }
                else
                {
                    string username = this.username.Text.Trim();//暂时备份用户名和密码
                    string password = this.password.Text.Trim();
                    string Enc = Md5(password);//md5加密密码

                    string constructor = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
                    MySqlConnection myCon = new MySqlConnection(constructor);
                    myCon.Open();//打开数据库

                    MySqlCommand myCmd = new MySqlCommand("UPDATE user_table SET times = times+1 where username = '" +username+ "' and password = '" + Enc + "';", myCon);
                    //更新pwd,N值自减1 times自增1(记录用户登录次数)
                    if (myCmd.ExecuteNonQuery() > 0)//通过影响的行数!=0 判断语句被执行
                    {
                        MessageBox.Show("登录成功!","提示");//插入数据库成功!
                        Username = username;// 用户名和密码变成全局变量
                        EnPwd = Enc;
                    }
                    else
                    {
                        MessageBox.Show("登录失败!用户名或密码错误!","提示");
                    }
                    myCon.Close();
                }

            }
            catch (Exception ex) //异常时执行下面语句
            {
                MessageBox.Show("运行出现错误!", "提示");
                //TextBox.AppendText("运行出现错误!" + "\r\n");
            }


        }

        /// <summary>
        /// 查看用户当前权限
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Check_Click(object sender, EventArgs e)
        {
            try
            {
                string constructorString = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
                MySqlConnection myConnnect = new MySqlConnection(constructorString);
                myConnnect.Open();//打开
                MySqlCommand myCmd = new MySqlCommand("SELECT * from resources where username='" +Username+ "'; ", myConnnect);
                MySqlDataReader dataReader = myCmd.ExecuteReader();//从数据库中读出当前的权限值(1,0),dataRearder[0-4]
                if (dataReader.HasRows)//如果存在数据
                {
                    dataReader.Read();//读取数据
                    string d1 = dataReader[0].ToString();//用户名
                    string d2 = dataReader[1].ToString();
                    string d3 = dataReader[2].ToString();
                    string d4 = dataReader[3].ToString();
                    string d5 = dataReader[4].ToString();
                    string d6 = dataReader[5].ToString();
                    TextBox.AppendText("用户"+d1+"拥有的权限"+"\r\n");
                    TextBox.AppendText("文件 1 2 3 4 5\r\n");//\r\n换行
                    TextBox.AppendText("权限 "+d2+" "+d3+" "+d4+" "+d5+" "+d6+"\r\n");
                    //一行输出//TextBox.AppendText("用户"+dataReader[0].ToString()+"的权限:"+"FILE1"+":"+dataReader[1].ToString()+" "+"FILE2"+":"+dataReader[2].ToString()+" "+"FILE3" +":"+dataReader[3].ToString() + " " + "FILE4"+":"+dataReader[4].ToString() + " " + "FILE5"+":"+dataReader[5].ToString()+"\r\n");
                }
                else
                {
                    MessageBox.Show("访问数据不存在!","提示");
                }
                myConnnect.Close();
            }
            catch (Exception ex) //异常时执行下面语句
            {
              MessageBox.Show("运行出现错误!", "提示");
                //TextBox.AppendText("运行出现错误!" + "\r\n");
            }


        }

        /// <summary>
        /// 访问文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void VisitFile_Click(object sender, EventArgs e)
        {
            try
            {

                string constructorString = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
                MySqlConnection myConnnect = new MySqlConnection(constructorString);
                myConnnect.Open();//打开

                string filenum = this.FileBox.Text.Trim();
                if (filenum == "")
                {
                    MessageBox.Show("文件名为空!", "提示");
                }
                else if (int.Parse(filenum) > 5|| int.Parse(filenum) <= 0)
                {
                    MessageBox.Show("没有此文件!", "提示");
                }
                else
                {
                    MySqlCommand myCmd = new MySqlCommand("SELECT FILE" + filenum + " from resources where username='" + Username + "'; ", myConnnect);
                    MySqlDataReader dataReader = myCmd.ExecuteReader();
                    if (dataReader.HasRows)//如果存在数据
                    {
                        dataReader.Read();//读取数据
                        string auth = dataReader[0].ToString();
                        if (auth.CompareTo("0") == 0)//比较,如果权限=0,提示无权访问
                        {
                            MessageBox.Show("用户无权访问该文件!", "提示");
                        }
                        else
                        {
                            MessageBox.Show("访问成功!", "提示");
                            //可以根据文件编号打开对应的TXT文件
                            System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();//定义一个ProcessStartInfo实例
                            info.WorkingDirectory = Application.StartupPath;//设置启动进程的初始目录
                            //info.FileName = @"test.txt";
                            string path = "file"+filenum+".txt";
                            info.FileName = path;
                            info.Arguments = "";//设置启动进程的参数
                            try
                            {
                                System.Diagnostics.Process.Start(info);//打开文件
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("文件打开失败!");
                            }

                        }

                    }
                }
            }
            catch (Exception ex) //异常时执行下面语句
            {
                MessageBox.Show("运行出现错误!", "提示");
                //TextBox.AppendText("运行出现错误!" + "\r\n");
            }
        }
        /// <summary>
        /// MD5加密函数
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string Md5(string text)
        {
        
            StringBuilder sb = new StringBuilder();
            MD5 md5 = MD5.Create();//创建MD5实例
            byte[] buffer = System.Text.Encoding.Default.GetBytes(text);//转换成byte[]
            byte[] Md5buffer = md5.ComputeHash(buffer);//加密
            //转换成16进制
            for (int i = 0; i < Md5buffer.Length; i++)
            {
                sb.Append(Md5buffer[i].ToString("X2"));  //x-->将10进制转换为16进制。2-->每次都是两位数输出。
            }
            md5.Clear();//释放MD5计算空间
            text = sb.ToString();
            return text;
        }


    }

   by 久违 2019.12.5
//管理员端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;   //引用MySql,记得引用库
using System.Security.Cryptography; //用于MD5加密

namespace 访问控制_管理员
{
    public partial class admin : Form
    {
        MySqlConnection SQLCon;
        MySqlCommand SQLCmd;
        public admin()
        {
            InitializeComponent();
        }


        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDLAd_Click(object sender, EventArgs e)
        {
            string Con = "server = 127.0.0.1; port = 3306; user = gust; password = gust; database = sk_test;";
            SQLCon = new MySqlConnection(Con);

            try
            {
                SQLCon.Open(); //连接数据库
                string searchStr = "SELECT * from resources";//sql语句
                MySqlDataAdapter adapter = new MySqlDataAdapter(searchStr, SQLCon);
                DataTable a = new DataTable();
                adapter.Fill(a);   //将查询的结果存到虚拟数据库a中的虚拟表tabuser中                                 
                this.DataGridView.DataSource = a;//将读取出来的内容显示到对话框
            }
            catch (Exception ex) //异常时执行下面语句
            {
                MessageBox.Show("运行出现错误!", "提示");
                //TextBox.AppendText("运行出现错误!" + "\r\n");
            }

        }

      
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Check_Click(object sender, EventArgs e)
        {
            string username = this.TextUser.Text.Trim();
            string filenum = this.TextFile.Text.Trim();
            string quan = this.TextQuan.Text.Trim();//数字1或0
            if (TextUser.Text == "" || TextFile.Text == "" || TextQuan.Text == "")//判空
            {
                MessageBox.Show("警告:用户名或文件名或权限值为空!", "提示");
            }
            else
            {
                try
                {
                    string searchStr = ("update resources set FILE" + filenum + "=" + quan + " where username='" + username + "';");
                    SQLCmd = new MySqlCommand(searchStr, SQLCon);
                    SQLCmd.ExecuteNonQuery();//执行
                    MessageBox.Show("修改成功!", "提示");
                    // bt_CONNECT_Click(sender, e);
                    TextUser.Text=""; 
                    TextFile.Text="";
                    TextQuan.Text="";//数字1或0
                }
                catch (MySqlException ex)
                {
                    MessageBox.Show("运行出现错误!", "提示");
                }
            }
        }

    }
}
by 久违 2019.12.5

运行效果图

新用户注册重名用户注册客户端登录成功客户端查看自己拥有的文件访问权限客户端访问file3,但是权限为0,所以无法访问客户端访问file2,权限为1,访问成功客户端访问了文件file2,上一步点了“确定”,文件自动打开管理员查看所有用户权限管理员修改111用户的file2权限,使111可以访问file2

实验总结与思考

1、 对访问控制的过程加深了理解
2、 对c#的运用和winform的使用更加熟练,但是有一些控件还是不熟悉其属性
3、 这次实验过程复杂,但是相对的前两次实验,实现的代码却相对简单,在梳理好流程之后代码成型很快。
4、 实验中遇到的几个问题以后需要注意:
A:MySqlDataAdapter数据类型的使用这里是第一次,之前使用的是MySqlDataReader,两者的区别如下:
DataReader是一个向前的指针,本身并不包含数据,调用一次Read()方法它就向前到下一条记录,一个DataReader必须单独占用一个打开的数据库连接!使用DataReader对象可以从数据库中得到只读的、只能向前的数据流,还可以提高应用程序的性能,减少系统开销,同一时间,只有一条行记录在内存中。
DataAdapter象一座桥梁,一头连起数据库表,一头连起一个DataSet或者DataTable,在把数据库中的数据填充到DataSet或DataTable后就可以“过河拆桥”,不用再连接到数据库,而可以直接从DataSet或DataTable中获取数据。
B:DataGridView的使用。之前的显示框一直使用的textbox控件,但是textbox控件只能显示单纯数据,不能以行列的形式显示表格,而DataGridView控件则很好的解决了这个问题,他可以虚拟出行列表格,这对显示数据库中的数据简直堪称完美,而且还支持对数据库表格的修改(虽然我没有用这个功能),管理员端用了这个控件省了不少的事。
C:数据库连接和关闭。因为实验涉及的连接数据库操作比较多,所以遇到打开数据库操作完成后没有及时关闭,数据库连接未关闭,直接导致了后面的连接无法读取数据出来。之前不知道,反复调试查错好久。所以要记着后面的打开的连接在操作完成之后顺手关闭连接,释放连接资源。
D:C#打开本地TXT文件:
System.Diagnostics.ProcessStartInfo的使用,创建进程去打开文件。要先实例化,然后设置进程的初始目录,给进程文件的绝对路径,然后执行打开文件操作,这个过程比C和python复杂好多啊。
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
//定义一个ProcessStartInfo实例
info.WorkingDirectory = Application.StartupPath;
//设置启动进程的初始目录
string path = “file.txt”;
info.FileName = path;
info.Arguments = “”;
//设置启动进程的参数
System.Diagnostics.Process.Start(info);
//打开文件

写下来算是记录,自己成长的过程吧
也算是对自己的一点点交代
(官方吐槽:我其实把管理员端的“登录”按钮在当“刷新”列表使用)
2019.12.6 发文

Logo

更多推荐