尝试用C#和winform实现界面版访问控制(基于MySQL5.7数据库)
用C#和winform实现界面版访问控制(基于MySQL5.7数据库)实验开发环境开发工具:Visual studio 2019操作系统:windows 10 家庭版语言:C#界面设计:winfrom窗体应用程序实验原理1969年,B.W.Lampson通过形式化表示方法运用主体、客体和访问控制矩阵的思想第一次对访问控制问题进行了抽象。主体是访问操作中的主动实体,客体是访问操作中的被...
用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
运行效果图
实验总结与思考
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 发文
更多推荐
所有评论(0)