1. 程式人生 > >用C#實現簡單的帶有驗證碼及密碼使用MD5加密的“登入”WinForm小程式

用C#實現簡單的帶有驗證碼及密碼使用MD5加密的“登入”WinForm小程式

初學C#Windows窗體程式時,做個簡單的“登入”是再簡單不過的了。像下面這樣的,功能稍理想了吧?

這裡寫圖片描述
這裡寫圖片描述
資料庫登陸表

有後臺數據庫,有驗證碼,資料庫中密碼是密文(如圖所示:資料庫中表資料是32位MD5加密的……)
下面講解如何實現。
步驟:
1、建立相應的資料庫,建立表,設定欄位及其屬性,設計觸發器
2、建立WinForm窗體程式
3、設計窗體
4、編輯程式碼
程式流程:
1、使用者輸入賬號、密碼,驗證碼
2、提交
3、連線資料庫、查詢密碼
4、成功匹配對應賬號密碼則跳轉到指定窗體,失敗則返回登陸窗體
要點:
1、前臺介面如何設計?
   ANS:使用label、textbox、button控制元件
2、後臺資料庫中密碼欄位如何加密為密文? 
   ANS:使用簡單的MD5加密演算法
3、前臺textbox中的資料如何和後臺資料庫中的密文匹配?
   ANS:將前臺textbox中的資料同樣加密,與後臺密文匹配。(加密演算法具有唯一性、單向性)
環境:
- 機器:windows 7 64 bit
- IDE:Visual Studio 2012 Ultimate
- 資料庫:SQL Server 2005

1、資料庫部分

資料庫使用兩張表,分別儲存使用者登入資訊及使用者註冊資訊。
1.1 表idpassword
|number|id|password|
|------|--|--------|    
1.2 表registerinformation

| number| id | password | name | mail |
|-------|----|----------|------|------|


 1、3 觸發器 trg_EncryptPwd
--sql觸發器,自動加密前臺傳入的密碼欄位
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER TRIGGER [trg_EncryptPwd]

ON  [dbo].[idpassword]

AFTER INSERT,UPDATE

AS 

BEGIN

    IF(UPDATE(password))

    BEGIN

        DECLARE @uid varchar(32)

        DECLARE @pwd varchar(32)

        -- 獲取使用者ID和密碼

        SELECT
@uid=id,@pwd=password FROM inserted -- 更新密碼 UPDATE idpassword SET password = dbo.MD5(@pwd,32) WHERE id = @uid END END -- 註冊使用者時,自動將使用者密碼加密。

2、前臺檢視

使用label、textbox、button控制元件。

3、程式碼

程式碼部分包含6位驗證碼(區分大小寫)的生成、WinForm窗體的跳轉、前臺textbox中密碼的加密、前臺輸入的賬號與後臺資料庫中的資料的匹配……

登入窗體程式碼:

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 System.Data.SqlClient;
using System.Data.Sql;
using System.Security.Cryptography;

/* 程式內容:實現簡單登陸程式,使用賬號,密碼登入。
 * 窗體:
 *       Login.cs :
 *       控制元件: label1  賬號:  label2 密碼:
 *             texId   賬號   texPwd  密碼
 *             button1 登陸   button2 註冊
 *             
 *       Register.cs
 *       控制元件: label1  賬號:  label2 密碼:label3 姓名: label4 郵箱:
 *             texId   賬號   texPwd  密碼  texName 姓名  texMail 郵箱
 *             button1 註冊   button2 重置
 * 
 * 作者:zhoujl
 * -------------------------2017年10月25日09:03:38----------------------
 * 
 */

namespace LoginDateBase
{
    public partial class Login : Form
    {
        //隨機碼的長度
        private const int iVerifyCodeLength = 6;
        //隨機碼
        private String strVerifyCode = "";
        public Login()
        {
            InitializeComponent();

            UpdateVerifyCode();
        }
        /// <summary>
        /// 更新驗證碼
        /// </summary>
        private void UpdateVerifyCode()
        {
            strVerifyCode = CreateRandomCode(iVerifyCodeLength);
            CreateImage(strVerifyCode);
        }
        /// <summary>
        /// 建立隨機碼圖片
        /// </summary>
        /// <param name="strVerifyCode"></param>
        private void CreateImage(string strVerifyCode)
        {
            try
            {
                int iRandAngle = 45;    //隨機轉動角度
                int iMapWidth = (int)(strVerifyCode.Length * 21);
                Bitmap map = new Bitmap(iMapWidth, 28);     //建立圖片背景

                Graphics graph = Graphics.FromImage(map);
                graph.Clear(Color.AliceBlue);//清除畫面,填充背景
                graph.DrawRectangle(new Pen(Color.Black, 0), 0, 0, map.Width - 1, map.Height - 1);//畫一個邊框
                graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//模式
                Random rand = new Random();
                //背景噪點生成
                Pen blackPen = new Pen(Color.LightGray, 0);
                for (int i = 0; i < 50; i++)
                {
                    int x = rand.Next(0, map.Width);
                    int y = rand.Next(0, map.Height);
                    graph.DrawRectangle(blackPen, x, y, 1, 1);
                }
                //驗證碼旋轉,防止機器識別
                char[] chars = strVerifyCode.ToCharArray();//拆散字串成單字元陣列
                //文字距中
                StringFormat format = new StringFormat(StringFormatFlags.NoClip);
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
                //定義顏色
                Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
                //定義字型
                string[] font = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋體" };
                for (int i = 0; i < chars.Length; i++)
                {
                    int cindex = rand.Next(7);
                    int findex = rand.Next(5);
                    Font f = new System.Drawing.Font(font[findex], 13, System.Drawing.FontStyle.Bold);//字型樣式(引數2為字型大小)
                    Brush b = new System.Drawing.SolidBrush(c[cindex]);
                    Point dot = new Point(16, 16);

                    float angle = rand.Next(-iRandAngle, iRandAngle);//轉動的度數
                    graph.TranslateTransform(dot.X, dot.Y);//移動游標到指定位置
                    graph.RotateTransform(angle);
                    graph.DrawString(chars[i].ToString(), f, b, 1, 1, format);

                    graph.RotateTransform(-angle);//轉回去
                    graph.TranslateTransform(2, -dot.Y);//移動游標到指定位置
                }
                pictureBox1.Image = map;

            }
            catch (ArgumentException)
            {
                MessageBox.Show("建立圖片錯誤。");
            }
        }
        /// <summary>
        /// 建立驗證碼
        /// </summary>
        /// <param name="iLength"></param>
        /// <returns></returns>
        private string CreateRandomCode(int iLength)
        {
            int rand;
            char code;
            string randomCode = String.Empty;
            //生成一定長度的驗證碼
            System.Random random = new Random();
            for (int i = 0; i < iLength; i++)
            {
                rand = random.Next();
                if (rand % 3 == 0)
                {
                    code = (char)('A' + (char)(rand % 26));
                }
                else
                {
                    code = (char)('0' + (char)(rand % 10));
                }
                randomCode += code.ToString();
            }
            return randomCode;
        }
        private void Login_Load(object sender, EventArgs e)
        {
            this.ActiveControl = this.txtId;
        }

        private void Login_Paint(object sender, PaintEventArgs e)
        {

        }
        /// <summary>
        /// 登陸
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //連線資料庫為SQL Server 2005

            //定義連結字串

            string connString = "server=.;user id=sa;password=sa;database=register";
            //1.建立連線物件
            SqlConnection conn = null;
            try
            {
                conn = new SqlConnection(connString);
            }
            catch (Exception e1)
            {
                e1.ToString();
                MessageBox.Show("建立連線物件出錯");
            }
            //md5 32位加密

            byte[] result = Encoding.Default.GetBytes(this.txtPwd.Text.Trim());  //輸入密碼的文字框
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] output = md5.ComputeHash(result);//加密後的登陸明文密碼
            this.txtPwd.Text = BitConverter.ToString(output).Replace("-", ""); //為輸出加密文字的文字框


            string sqlLog = "select * from idpassword where id='"
                + txtId.Text.Trim() + "'and password='" + this.txtPwd.Text + "'  ";
            try
            {
                //2.開啟連線
                conn.Open();
            }
            catch (Exception e2)
            {
                e2.ToString();
                MessageBox.Show("資料庫連接出錯");
            }

            if (txtId.Text.Equals("") || txtPwd.Text.Equals(""))//賬號,密碼為空
            {
                MessageBox.Show("請輸入賬號密碼");
            }
            else if (textBox1.Text.Equals("") || !textBox1.Text.Equals(strVerifyCode))//驗證碼為空或錯誤
            {
                MessageBox.Show("驗證碼錯誤");
            }
            else
            {
                //資料庫tra-sql語句
                //3.執行查詢
                SqlCommand cmdL = new SqlCommand(sqlLog, conn);
                //從資料庫讀一行
                SqlDataReader sread = cmdL.ExecuteReader();
                int count = 0;
                while (sread.Read())
                {
                    count++;
                }
                //4.關閉連線
                conn.Close();
                if (count > 0)
                {
                    MessageBox.Show("登陸成功");
                    //登陸成功則跳轉至新的窗體

                    Search search = new Search();
                    //查詢視窗
                    search.Show();
                }
                else
                {
                    MessageBox.Show("登入失敗");
                }

            }

        }

        private void button2_Click(object sender, EventArgs e)//註冊
        {
            Register form2 = new Register();
            form2.Show();
        }
        /// <summary>
        /// 重新整理驗證碼
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)//更換驗證碼
        {
            UpdateVerifyCode();
        }

    }

}

註冊窗體程式碼

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 System.Data.SqlClient;
using System.Data.Sql;

namespace LoginDateBase
{
    public partial class Register : Form
    {
        public Register()
        {
            InitializeComponent();
        }
        //清空輸入
        public void c()
        {
            txtIdR.Text = "";
            txtPwdR.Text = "";
            txtName.Text = "";
            txtMail.Text = "";
        }


        private void Registe_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            //輸入不能為空
            if (txtIdR.Text == "" | txtPwdR.Text == "" | txtName.Text == "" | txtMail.Text == "")
            {
                MessageBox.Show("請輸入完整資訊");
                return;
            }
            ///LoginId不能為重複
            //定義連結字串
            string connString = "server=.;user id=sa;password=sa;database=register";

            //1.建立連線物件
            SqlConnection conn = new SqlConnection(connString);
            //組合sql查詢語句
            string sqlSelect = "select id from registerinformation where id='" + txtIdR.Text.Trim() + "'";
            SqlCommand cmd1 = new SqlCommand(sqlSelect, conn);

            //2.開啟連線 
            //3.執行查詢
            conn.Open();
            object result1 = cmd1.ExecuteScalar();
            //判斷賬號是否重複
            if (result1 != null)
            {
                MessageBox.Show("該賬戶已被註冊");
                conn.Close();
                return;
            }
            //4.關閉連線
            conn.Close();


            //添加註冊資訊SQL語句
            string sql = "insert into registerinformation(id,password,name,mail)";
            sql += "values('{0}','{1}','{2}','{3}')";
            sql = string.Format(sql, txtIdR.Text, txtPwdR.Text, txtName.Text, txtMail.Text);

            SqlCommand cmd = new SqlCommand(sql, conn);
            //開啟連線
            conn.Open();
            //執行操作
            int reslt = cmd.ExecuteNonQuery();
            conn.Close();
            //清空輸入
            c();
            //註冊成功
            MessageBox.Show("註冊成功");
            this.Close();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            c();
            txtIdR.Focus();
        }
    }
}

後記:

       時間倉促,本人水平也有限,若各位讀者發現錯誤歡迎批評指正!