[C#SQLite+跨窗体操作]登录功能与权限管理的实现

        在软件开发过程中,登录功能、注册功能以及对应的不同账号的操作权限十分常见。本文讨论.NET平台C#语言如何开发窗体界面的登录注册功能。

        具体思路为,在本地创建数据库文件保存用户名与密码信息,软件中的LoginForml类查询数据库登录,Regist类写入数据库注册。登录后跨窗体改变控件的使能(Enabled)等属性,实现权限控制。

涉及到的重点知识包括:

        1. SQLite数据库文件读写

        2. 跨窗体控件操作(子窗体控制夫窗体+父窗体控制子窗体)

        3. 编码加密的思维

目录

零、预备知识: SQLite与数据库文件.db

        1. 环境搭建:

        2. 文件准备:

        3. SQLite读写命令

一、SQLite 注册操作

二、SQLite登录操作

三、跨窗体控件控制

1. 子窗体控制父窗体

2. 父窗体修改子窗体的方法1

3. 父窗体修改子窗体的方法2(初始化参数)


零、预备知识: SQLite与数据库文件.db

        1. 环境搭建:

          要在.NET平台使用SQLite数据库,需要右键解决方案,选择NuGet包管理,搜索System.Data.SQLite,安装。在代码前加using System.Data.SQLite; 即可调用。

        2. 文件准备:

        本文不涉及创建数据库的操作,只涉及数据库的读写,想知道更完整的数据库操作命令,请期待本人其他文章(写完了会放链接)。因为登录与注册操作文件格式固定的特点,读者可以在本地创建一个文件,后缀修改为.db,例如:login,db。本文后面的数据库操作就用login.db指代数据库文件名。

        想直观地查看和修改数据库文件,可以安装轻量级数据库小程序SQLIteExpertPro,也可以在Visual Studio Code装SQL插件。

SQLiteExpertPro的下载链接如下

链接:https://pan.baidu.com/s/18stalFuKbXISRfvpaVLKSw?pwd=HFSS 
提取码:HFSS 

 

        编辑login.db,添加若干个table(表),账户分几级就创建多少表。这里创建三个表单,分别命名为admin(管理员)、monitor(巡检员)、worker(工人)。给每个表单添加两个TEXT列,一个命名为用户名,第二列命名为密码。

至此,文件准备好了。

        3. SQLite读写命令

3.1 打开.db文件 

//等号后为数据库文件的地址
string conStr = "data source= /bin/Debug/login.db;version=3;";
using (SQLiteConnection connect = new SQLiteConnection(conStr))
{
    //打开文件
    connect.Open();
    //读写操作
    //...
    //读写操作结束
    //关闭文件
    connect.Close();
}
            

3.2 读.db文件(SELECT)

public void Read()
{
//等号后为数据库文件的地址
string conStr = "data source= "+FilePath+“;version=3;";
using (SQLiteConnection connect = new SQLiteConnection(conStr))
{
    //打开文件
    connect.Open();
    //读操作
    using (SQLiteCommand fmd = connect.CreateCommand())
    {
        //table与name自行替换成具体的表名与元素名
        //从table中选中用户名=name的行,只返回选中行的用户名项与密码项
        //name两端一定要加引号,否则会报错SQLite Logic Error
        fmd.CommandText = "SELECT 用户名,密码 FROM "+table+" WHERE 用户名=" +'"'+ name+'"';
        fmd.ExecuteScalar();
        using (SQLiteDataReader reader = fmd.ExecuteReader())
        {
           //一行行读取
           while (reader.Read())
           {
            //读取当前行    
            //获取密码
            //第0列是用户名,第一列是密码,都是字符串TEXT格式
            string s = (string)reader["密码”];
            //也可以写成string s = (string)reader[1];
           }
        }
        //读写操作结束
        //关闭文件
    }
}

}

       

3.3 写.db文件

//打开.db文件
//FilePath是文件地址
string conStr = "data source=" + FilePath + ";version=3;";
using (SQLiteConnection connect = new SQLiteConnection(conStr))
{
    //打开文件
	connect.Open();
	using (SQLiteCommand fmd = connect.CreateCommand())
	{
		SQLiteCommand cmd = new SQLiteCommand();
        //table替换为表名,name替换为元素名
		cmd.CommandText = "INSERT INTO "+table+" VALUES(" + "\"" + name + "\"" + "," + "\"" + pw + "\"" + ")";
		cmd.ExecuteNonQuery();
		connect.Close();
    }
}		

一、SQLite 注册操作

        在注册窗体上创建文本框控件textBox_name与textBox_password, 用于输入用户名与密码字符串。新建一个Hash类,添加public static string HashEncoding(string s)方法,加密原始密码后再存入数据库,提升安全性能。在后续的登录环节还会用到这个HashEncoding方法,把输入的密码用同样的逻辑加密,比照数据库对应内容,判断密码是否正确。

        private void Regist()
		{
            //表名
			string table = "admin";
			
			//若输入框为空,报错
			if (textBox_name.Text == "" || textBox_password.Text == "")
			{
				MessageBox.Show("用户名或密码不能为空");
				return;
			}
			//打开数据库的命令
			string conStr = "data source=" + GetFilePath() + ";version=3;";
			using (SQLiteConnection connect = new SQLiteConnection(conStr))
			{
				connect.Open();
				int count=0;
				using (SQLiteCommand fmd = connect.CreateCommand())
				{
					fmd.CommandText =SearchName(textBox_name.Text.Trim(),table);
					fmd.ExecuteScalar();
					using (SQLiteDataReader reader = fmd.ExecuteReader())
					{
						while (reader.Read())
						{
							count++;
						}
					}
					connect.Close();
				}
				if(count > 0)
				{
					label_info.Text= "用户名已存在,请直接登录";
					return;
				}
			}
            //Hash类有public static方法HashEncoding(string s)对密码进行加密
			string codedCode = Hash.HashEncoding(textBox_password.Text.Trim());
			Console.WriteLine(codedCode);
			using (SQLiteConnection connect = new SQLiteConnection(conStr))
			{
				SQLiteCommand cmd = new SQLiteCommand();
				cmd.Connection = connect;
				connect.Open();
				cmd.CommandText = Insert(textBox_name.Text.Trim(), codedCode,table);
				try
				{
					cmd.ExecuteNonQuery();
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message);
				}
				connect.Close();
			}
			label_info.Text = "注册成功";
		}
        private string Insert(string name,string pw,string table)
		{
			return string.Format("INSERT INTO "+table+" VALUES(" + "\"" + name + "\"" + "," + "\"" + pw + "\"" + ")");
    
		}
		private static string GetFilePath()
		{
			string path = System.IO.Directory.GetCurrentDirectory();
			return System.IO.Path.Combine(path, "login.db");
		}
	
		private string SearchName(string name,string table)
		{
			
				return "SELECT 用户名,密码  FROM "+table+" WHERE 用户名=" + '"'+name+'"';

           
		}

二、SQLite登录操作

        //若成功登录,返回true,否则返回false
        private bool Succeeded(string name, string password, string table)
		{
            string truecode="";
            string conStr = "data source=" + GetFilePath() + ";version=3;";
            using (SQLiteConnection connect = new SQLiteConnection(conStr))
            {
                connect.Open();
                int count = 0;
                using (SQLiteCommand fmd = connect.CreateCommand())
                {
                    fmd.CommandText = SearchName(name,table);
                    fmd.ExecuteScalar();
                    using (SQLiteDataReader reader = fmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            truecode = (string)reader["密码"];
                            count++;
                        }
                    }
                    connect.Close();
                }
                if (count==0)
                {
                    MessageBox.Show("用户名不存在");
                    return false;
                }
                else
                {
                    if(Hash.HashEncoding(password)==truecode)
                    {
                        if (table == "admin")
                        {
                            //管理员权限操作
                        }
                        else if(table == "monitor")
                        {
                            //巡检员权限操作
                        }
                        else if(table == "worker")
                        {
                           //操作工权限操作
                        }
                        MessageBox.Show("登录成功");
                    }
                    else
                    {
                        MessageBox.Show("密码错误");
                    }
                }
            }
            return false;
		}
        private static string GetFilePath()
        {
            string path = System.IO.Directory.GetCurrentDirectory();
            return System.IO.Path.Combine(path, "login.db");
        }
        private string SearchName(string name, string table)
        {
            
                return "SELECT 用户名,密码 FROM "+table+" WHERE 用户名=" +'"'+ name+'"';

           
        }

三、跨窗体控件控制

1. 子窗体控制父窗体

这里用一个定义在Owner窗体类的public static f1变量实现子窗体对Owner窗体的控制。父窗体类命名为Form1,子窗体类为LoginForm。

父窗体内代码

public partial class Form1 : Form
{
    public static Form1 f1;
    private LoginForm lf = new LoginForm();
    pubulic Form1()
    {
        f1 = this;
        lf.Owner = this;
    }
}

子窗体内代码

public partial class LoginForm : Form
{
	Form1 f1;
    public bool IsAdmin;
	public LoginForm()
	{
		InitializeComponent();
		f1= (Form1)this.Owner;
	}
    private void Action()
    {
        //选择任意Form1中的修饰符为public的控件或变量进行修改
        Form1.f1.button1.Enabled = true;
    }
}

        值得指出的是,拖拽生成的控件默认访问修饰符为private,如果需要跨窗体访问,需要将修饰符改为public。修改方式是,选中控件,右键属性,找到Modifier栏。 如果控件由代码生成,在代码中修改访问修饰符即可。

2. 父窗体修改子窗体的方法1

        方法1类似于子窗体修改父窗体的方法,就是用static变量。static修饰符已经修改,该类的所有实例的对应值都会修改。这样可以避免多次创建实例后变量值不一致。

3. 父窗体修改子窗体的方法2(初始化参数)

        方法2的大致思路是,给子类的初始化添加形参,实例化子类的变量由父窗体提供。

        子窗体内代码

public Regist(bool IsAdmin)
{
	InitializeComponent();
	if (IsAdmin)
	{
		//相应操作
	}
	else
	{
        //相应操作
    }
}

父窗体内代码

Regist rg = new Regist(IsAdmin);
rg.ShowDialog();

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值