數據庫結構檢查 表名、表字段、觸發器 檢查 輸出日誌

/// <summary>
    /// 數據庫安全(此類用於檢測數據庫穩定運行的安全監測)
    /// </summary>
    public class DatabaseSecurity
    {

        /// <summary>
        /// 結構檢測
        /// </summary>
        public static void StructDetection()
        {
            //檢測步驟
            //1.表總數檢測 檢測缺少什麼表
            //2.檢測每個表是否缺少那些字段
            var FeedbackTableNames = GlobalVariable.DatabaseFile.SelectMySQL("select * from information_schema.tables WHERE table_schema ='phi'; ");
            if (!FeedbackTableNames.status)
            {
                //檢測失敗
            }
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            //數據庫現在的表
            List<string> TableNames = FeedbackTableNames.result.AsEnumerable().Select<DataRow, string>(x => x["TABLE_NAME"].ToString()).ToList<string>();
            //官方發佈的數據庫表表
            List<string> TableNamesOld = Resources.DBSafe_TableNames.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();

#if DEBUG
            File.WriteAllLines(@"d:\\DBSafe_TableNames.txt", TableNames.ToArray());
#endif
            //檢測表是否缺失
            List<string> TableNamesLost = TableNamesOld.Except(TableNames).ToList();
            if (TableNamesLost.Count > 0)
            {
                LogHelper.Instance.Error("缺失表" + string.Join(",", TableNamesLost.ToArray()));
                //System.Windows.MessageBox.Show("");
            }

            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/

            //對每一個表 結構名稱進行遍歷 檢測表結構是否不匹配

            var FeedbackTableStructss = GlobalVariable.DatabaseFile.SelectMySQL("select * from information_schema.columns where table_schema = 'phi' ; ");
            if (!FeedbackTableStructss.status)
            {
                //檢測失敗
            }
            //數據庫每個個表現在的結構
            List<Table_Struct> TableStructs = new List<Table_Struct>();
            TableStructs = FeedbackTableStructss.result.TableToList<Table_Struct>();
#if DEBUG
            File.WriteAllText(@"d:\\DBSafe_Structs.txt", JsonConvert.SerializeObject(TableStructs));
#endif
            //官方發佈的數據庫表結構
            List<Table_Struct> TableStructsOld = JsonConvert.DeserializeObject<List<Table_Struct>>(Resources.DBSafe_Structs);

            //檢測表結構是否完整
            foreach (var itemTableName in TableNames)
            {

                var TableNow = TableStructs.Where(x => x.TABLE_NAME == itemTableName).ToList();
                var TableOld = TableStructsOld.Where(x => x.TABLE_NAME == itemTableName).ToList();
                //檢測表結構是否完整
                List<Table_Struct> TableStructsLost = TableOld.Except(TableNow).ToList();
                if (TableStructsLost.Count > 0)
                {
                    LogHelper.Instance.Error(itemTableName + "_結構不一致,請檢查以下字段_" + string.Join(",", TableStructsLost.Select(x => x.COLUMN_NAME).ToArray()));
                    LogHelper.Instance.Error(JsonConvert.SerializeObject(TableStructsLost));
                    //System.Windows.MessageBox.Show("");
                }
            }

            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/
            /*--------------------------------------------------------------------------------------------------------------------------------------------*/

            var FeedbackTableTriggers = GlobalVariable.DatabaseFile.SelectMySQL("SELECT * FROM information_schema.`TRIGGERS` WHERE TRIGGER_SCHEMA='phi';");
            if (!FeedbackTableTriggers.status)
            {
                //檢測失敗
            }
            //數據庫每個個表現在的觸發器
            List<Table_Trigger> TableTrigger = new List<Table_Trigger>();
            TableTrigger = FeedbackTableTriggers.result.TableToList<Table_Trigger>();
#if DEBUG
            File.WriteAllText(@"d:\\DBSafe_Triggers.txt", JsonConvert.SerializeObject(TableTrigger));
#endif
            //官方發佈的數據庫觸發器
            List<Table_Trigger> TableTriggerOld = JsonConvert.DeserializeObject<List<Table_Trigger>>(Resources.DBSafe_Triggers);

            //檢測觸發器是否完整
            foreach (var itemTableName in TableNames)
            {
                var TableNow = TableTrigger.Where(x => x.EVENT_OBJECT_TABLE == itemTableName).ToList();
                var TableOld = TableTriggerOld.Where(x => x.EVENT_OBJECT_TABLE == itemTableName).ToList();
                //檢測觸發器構是否完整
                List<Table_Trigger> TableTriggersLost = TableOld.Except(TableNow).ToList();
                //多出的觸發器
                List<Table_Trigger> TableTriggersMore = TableNow.Except(TableOld).ToList();
                foreach (var item in TableTriggersMore)
                {
                    var feedbackDrop = GlobalVariable.DatabaseFile.UpdateMySQL(item.GetMysqlDropTriggerString());
                    if (feedbackDrop.status)
                    {
                        LogHelper.Instance.Error("刪除觸發器_" + item.TRIGGER_NAME + JsonConvert.SerializeObject(item));
                    }
                }
                if (TableTriggersLost.Count > 0)
                {
                    LogHelper.Instance.Error(itemTableName + "_觸發器不一致,請檢查以下觸發器_" + string.Join(",", TableTriggersLost.Select(x => x.TRIGGER_NAME).ToArray()));
                    LogHelper.Instance.Error(JsonConvert.SerializeObject(TableTriggersLost));
                    //System.Windows.MessageBox.Show("");
                }
            }

            //測試添加觸發器
            //var test1 = TableTrigger.FirstOrDefault();
            //var feedback = GlobalVariable.DatabaseFile.InsertMySQL(test1.GetMysqlCreateTriggerString());
        }

        public class Table_Struct
        {
            public string TABLE_SCHEMA { get; set; }
            public string TABLE_NAME { get; set; }
            public string COLUMN_NAME { get; set; }
            public string DATA_TYPE { get; set; }
            public string IS_NULLABLE { get; set; }
            public string COLUMN_TYPE { get; set; }
            public string COLUMN_COMMENT { get; set; }

            public override bool Equals(object obj)
            {
                var temp = obj as Table_Struct;
                return this.TABLE_SCHEMA == temp.TABLE_SCHEMA && this.TABLE_NAME == temp.TABLE_NAME && this.COLUMN_NAME == temp.COLUMN_NAME && this.COLUMN_TYPE == temp.COLUMN_TYPE;
            }

            public override int GetHashCode()
            {
                return (this.TABLE_SCHEMA + this.TABLE_NAME + this.COLUMN_NAME + this.COLUMN_TYPE).GetHashCode();
            }
        }



        public class Table_Trigger
        {
            public string TRIGGER_SCHEMA { get; set; }
            public string EVENT_OBJECT_SCHEMA { get; set; }
            public string EVENT_OBJECT_TABLE { get; set; }
            public string TRIGGER_NAME { get; set; }
            public string EVENT_MANIPULATION { get; set; }
            public string ACTION_TIMING { get; set; }
            public string ACTION_STATEMENT { get; set; }

            /// <summary>
            /// 刪除觸發器
            /// </summary>
            /// <returns></returns>
            public string GetMysqlDropTriggerString()
            {
                string mysqlStr = string.Format("DROP TRIGGER IF EXISTS `{0}`; DELIMITER ; ; ", this.TRIGGER_NAME);
                return mysqlStr;
            }
            /// <summary>
            /// 創建更新觸發器
            /// </summary>
            /// <returns></returns>
            public string GetMysqlCreateTriggerString()
            {
                string mysqlStr = string.Format("DROP TRIGGER IF EXISTS `{0}`; DELIMITER ; ; create trigger {0} {1} {2} on {3} for each row {4}",
                    this.TRIGGER_NAME,
                    this.ACTION_TIMING,
                    this.EVENT_MANIPULATION,
                    this.EVENT_OBJECT_TABLE,
                    this.ACTION_STATEMENT.Replace("\r\n", "\n").Replace("\"", "\'"));
                return mysqlStr;
            }


            public override bool Equals(object obj)
            {
                var temp = obj as Table_Trigger;
                var paraments = typeof(Table_Trigger).GetProperties();
                var result = paraments.Where(item => item.GetValue(this).GetHashCode() != item.GetValue(obj).GetHashCode()).ToList();
                if (result == null)
                {
                    return true;
                }
                return result.Count() <= 0;
            }

            public override int GetHashCode()
            {
                var paraments = typeof(Table_Trigger).GetProperties();
                var hash = paraments.Select(item => item.GetValue(this).GetHashCode()).ToArray();
                return (string.Join("", hash)).GetHashCode();
            }


        }

    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章