Jelajahi Sumber

Добавить 'Лекции/2.5.800_Управление_доступом_и_контроль_печати_конфиденциальной_информации/Guzeev.py'

u23-27guzeev 5 hari lalu
induk
melakukan
ad6d96174a

+ 333 - 0
Лекции/2.5.800_Управление_доступом_и_контроль_печати_конфиденциальной_информации/Guzeev.py

@@ -0,0 +1,333 @@
+import tkinter as tk
+from tkinter import ttk, messagebox
+import random
+import time
+try:
+    import winsound
+    SOUND_ENABLED = True
+except:
+    SOUND_ENABLED = False
+
+class SecurityGame:
+    def __init__(self, root):
+        self.root = root
+        self.root.title("Игра: Управление доступом и контроль печати")
+        self.root.geometry("900x700")
+        self.root.configure(bg="#2c3e50")
+        
+        # Стили
+        self.style = ttk.Style()
+        self.style.theme_use("clam")
+        self.style.configure("TLabel", background="#2c3e50", foreground="white", font=("Arial", 11))
+        self.style.configure("TButton", font=("Arial", 11, "bold"), background="#3498db")
+        self.style.configure("TFrame", background="#2c3e50")
+        
+        # Переменные
+        self.current_scene = 0
+        self.scenes = [self.scene1, self.scene2, self.scene3, self.scene4, self.scene5]
+        self.score = 0
+        
+        # Заголовок и прогресс
+        self.header_frame = tk.Frame(root, bg="#1a252f", height=80)
+        self.header_frame.pack(fill=tk.X)
+        self.title_label = tk.Label(self.header_frame, text="Управление доступом и контроль печати", font=("Arial", 18, "bold"), fg="#ecf0f1", bg="#1a252f")
+        self.title_label.pack(pady=10)
+        self.progress = ttk.Progressbar(self.header_frame, length=400, mode='determinate')
+        self.progress.pack(pady=5)
+        self.score_label = tk.Label(self.header_frame, text="Очки: 0", font=("Arial", 12), fg="#f1c40f", bg="#1a252f")
+        self.score_label.pack()
+        
+        # Основной фрейм для сцен
+        self.main_frame = tk.Frame(root, bg="#2c3e50")
+        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
+        
+        # Фрейм для подсказок
+        self.hint_frame = tk.Frame(root, bg="#34495e", height=50)
+        self.hint_frame.pack(fill=tk.X, side=tk.BOTTOM)
+        self.hint_label = tk.Label(self.hint_frame, text="Нажми 'Подсказка' для помощи", font=("Arial", 10), fg="#bdc3c7", bg="#34495e")
+        self.hint_label.pack(pady=5)
+        
+        self.load_scene()
+    
+    def play_sound(self, success=True):
+        if SOUND_ENABLED:
+            if success:
+                winsound.Beep(1000, 200)
+            else:
+                winsound.Beep(400, 500)
+    
+    def update_progress(self):
+        value = (self.current_scene / len(self.scenes)) * 100
+        self.progress['value'] = value
+        self.score_label.config(text=f"Очки: {self.score}")
+    
+    def show_hint(self, hint_text):
+        self.hint_label.config(text=f"💡 Подсказка: {hint_text}", fg="#f1c40f")
+        self.hint_frame.configure(bg="#2c3e50")
+        self.root.after(5000, lambda: self.hint_label.config(text="Нажми 'Подсказка' для помощи", fg="#bdc3c7", bg="#34495e"))
+    
+    def clear_frame(self):
+        for widget in self.main_frame.winfo_children():
+            widget.destroy()
+    
+    def animate_widget(self, widget, color_from, color_to, steps=10):
+        """Простая анимация смены цвета фона виджета"""
+        r1, g1, b1 = self.hex_to_rgb(color_from)
+        r2, g2, b2 = self.hex_to_rgb(color_to)
+        for i in range(steps+1):
+            r = r1 + (r2 - r1) * i // steps
+            g = g1 + (g2 - g1) * i // steps
+            b = b1 + (b2 - b1) * i // steps
+            color = f"#{r:02x}{g:02x}{b:02x}"
+            widget.configure(bg=color)
+            self.root.update()
+            time.sleep(0.02)
+    
+    def hex_to_rgb(self, hex_color):
+        hex_color = hex_color.lstrip('#')
+        return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
+    
+    def load_scene(self):
+        self.clear_frame()
+        self.update_progress()
+        self.scenes[self.current_scene]()
+    
+    def next_scene(self):
+        self.current_scene += 1
+        self.score += 10
+        self.update_progress()
+        if self.current_scene < len(self.scenes):
+            self.load_scene()
+        else:
+            messagebox.showinfo("Поздравляем!", f"Вы успешно завершили игру!\nФинальный счёт: {self.score} очков.\nТеперь вы эксперт по безопасности!")
+            self.root.quit()
+    
+    # СЦЕНА 1: Выбор модели доступа с анимацией
+    def scene1(self):
+        tk.Label(self.main_frame, text="СЦЕНА 1: Модели управления доступом", font=("Arial", 16, "bold"), fg="#ecf0f1", bg="#2c3e50").pack(pady=10)
+        tk.Label(self.main_frame, text="Сопоставьте описание с правильной моделью (DAC, MAC, RBAC):", font=("Arial", 12), fg="#bdc3c7", bg="#2c3e50").pack(pady=5)
+        
+        questions = [
+            ("Владелец ресурса сам назначает права (например, через ACL).", "DAC"),
+            ("Объектам и субъектам присваиваются метки конфиденциальности, решение принимает система.", "MAC"),
+            ("Права группируются по должностным ролям, пользователь получает доступ через роль.", "RBAC")
+        ]
+        
+        self.answers = {}
+        self.vars = []
+        
+        for i, (desc, correct) in enumerate(questions):
+            frame_q = tk.Frame(self.main_frame, bg="#2c3e50")
+            frame_q.pack(fill=tk.X, padx=20, pady=5)
+            tk.Label(frame_q, text=desc, wraplength=600, anchor="w", justify=tk.LEFT, fg="white", bg="#2c3e50").pack(side=tk.LEFT, padx=5)
+            var = tk.StringVar(frame_q)
+            var.set("")
+            self.vars.append(var)
+            combo = ttk.Combobox(frame_q, textvariable=var, values=["DAC", "MAC", "RBAC"], state="readonly", width=10)
+            combo.pack(side=tk.RIGHT, padx=5)
+            self.answers[i] = correct
+        
+        def check():
+            correct_count = 0
+            for i, var in enumerate(self.vars):
+                if var.get() == self.answers[i]:
+                    correct_count += 1
+            if correct_count == 3:
+                self.play_sound(True)
+                self.animate_widget(self.main_frame, "#2c3e50", "#27ae60", steps=8)
+                messagebox.showinfo("Верно", "Все модели определены правильно!")
+                self.next_scene()
+            else:
+                self.play_sound(False)
+                self.animate_widget(self.main_frame, "#2c3e50", "#c0392b", steps=8)
+                messagebox.showerror("Ошибка", f"Правильно: {correct_count} из 3. Попробуйте ещё раз.")
+        
+        btn = tk.Button(self.main_frame, text="Проверить", command=check, bg="#3498db", fg="white", font=("Arial", 12, "bold"), relief=tk.RAISED, padx=20, pady=5)
+        btn.pack(pady=20)
+        
+        hint_btn = tk.Button(self.main_frame, text="Подсказка", command=lambda: self.show_hint("DAC — владелец решает, MAC — метки, RBAC — роли"), bg="#f39c12", fg="white")
+        hint_btn.pack(pady=5)
+    
+    # СЦЕНА 2: Назначение прав (используем Canvas для красивого отображения)
+    def scene2(self):
+        tk.Label(self.main_frame, text="СЦЕНА 2: Принцип минимальных привилегий", font=("Arial", 16, "bold"), fg="#ecf0f1", bg="#2c3e50").pack(pady=10)
+        tk.Label(self.main_frame, text="Для каждой роли отметьте разрешённые объекты (только необходимое):", font=("Arial", 12), fg="#bdc3c7", bg="#2c3e50").pack(pady=5)
+        
+        roles = ["Бухгалтер", "Кадровик", "Сисадмин", "Стажёр"]
+        objects = ["Зарплата", "Личные дела", "Журналы сервера", "Общие инструкции"]
+        correct = [
+            [True, False, False, False],
+            [False, True, False, False],
+            [False, False, True, False],
+            [False, False, False, True]
+        ]
+        
+        self.check_vars = []
+        # Создаём таблицу с цветными ячейками
+        canvas = tk.Canvas(self.main_frame, bg="#2c3e50", highlightthickness=0)
+        canvas.pack(fill=tk.BOTH, expand=True)
+        
+        # Заголовки
+        for j, obj in enumerate(objects):
+            canvas.create_text(200 + j*120, 50, text=obj, fill="white", font=("Arial", 10, "bold"))
+        for i, role in enumerate(roles):
+            canvas.create_text(80, 100 + i*60, text=role, fill="#f1c40f", font=("Arial", 11, "bold"), anchor="w")
+        
+        self.check_boxes = []
+        for i in range(len(roles)):
+            row = []
+            for j in range(len(objects)):
+                var = tk.BooleanVar(value=False)
+                chk = tk.Checkbutton(self.main_frame, variable=var, bg="#2c3e50", selectcolor="#2c3e50", activebackground="#2c3e50")
+                # размещаем через create_window
+                window_id = canvas.create_window(200 + j*120, 100 + i*60, window=chk, anchor=tk.CENTER)
+                row.append(var)
+            self.check_boxes.append(row)
+        
+        def check2():
+            ok = True
+            for i in range(len(roles)):
+                for j in range(len(objects)):
+                    if self.check_boxes[i][j].get() != correct[i][j]:
+                        ok = False
+                        break
+                if not ok:
+                    break
+            if ok:
+                self.play_sound(True)
+                self.animate_widget(self.main_frame, "#2c3e50", "#27ae60", steps=8)
+                messagebox.showinfo("Верно", "Права назначены правильно!")
+                self.next_scene()
+            else:
+                self.play_sound(False)
+                self.animate_widget(self.main_frame, "#2c3e50", "#c0392b", steps=8)
+                messagebox.showerror("Ошибка", "Нарушен принцип минимальных привилегий. Стажёр не должен видеть зарплату, а бухгалтер — журналы.")
+        
+        btn = tk.Button(self.main_frame, text="Проверить", command=check2, bg="#3498db", fg="white", font=("Arial", 12, "bold"))
+        btn.pack(pady=20)
+        hint_btn = tk.Button(self.main_frame, text="Подсказка", command=lambda: self.show_hint("Каждой роли — только её данные: бухгалтеру зарплата, кадровику личные дела и т.д."), bg="#f39c12", fg="white")
+        hint_btn.pack(pady=5)
+    
+    # СЦЕНА 3: Настройка безопасной печати (с анимацией кнопок)
+    def scene3(self):
+        tk.Label(self.main_frame, text="СЦЕНА 3: Безопасная печать", font=("Arial", 16, "bold"), fg="#ecf0f1", bg="#2c3e50").pack(pady=10)
+        tk.Label(self.main_frame, text="Выберите корректные параметры для печати конфиденциальных документов:", font=("Arial", 12), fg="#bdc3c7", bg="#2c3e50").pack(pady=5)
+        
+        # Принтер
+        tk.Label(self.main_frame, text="Принтер:", fg="white", bg="#2c3e50").pack(anchor=tk.W)
+        self.printer_var = tk.StringVar(value="Общий")
+        printers = ["Общий принтер в холле", "Принтер в переговорной", "Принтер в сейфовой комнате"]
+        for p in printers:
+            tk.Radiobutton(self.main_frame, text=p, variable=self.printer_var, value=p, bg="#2c3e50", fg="white", selectcolor="#2c3e50").pack(anchor=tk.W)
+        
+        # Время удаления
+        tk.Label(self.main_frame, text="Время автоудаления:", fg="white", bg="#2c3e50").pack(anchor=tk.W, pady=(10,0))
+        self.time_var = tk.IntVar(value=5)
+        times = [5, 15, 30]
+        for t in times:
+            tk.Radiobutton(self.main_frame, text=f"{t} мин", variable=self.time_var, value=t, bg="#2c3e50", fg="white", selectcolor="#2c3e50").pack(anchor=tk.W)
+        
+        # Аутентификация
+        self.auth_var = tk.BooleanVar(value=True)
+        tk.Checkbutton(self.main_frame, text="Требовать аутентификацию у принтера", variable=self.auth_var, bg="#2c3e50", fg="white", selectcolor="#2c3e50").pack(anchor=tk.W)
+        
+        def check3():
+            correct = (self.printer_var.get() == "Принтер в сейфовой комнате" and self.time_var.get() == 5 and self.auth_var.get() == True)
+            if correct:
+                self.play_sound(True)
+                self.animate_widget(self.main_frame, "#2c3e50", "#27ae60", steps=8)
+                messagebox.showinfo("Верно", "Настройки безопасной печати корректны!")
+                self.next_scene()
+            else:
+                self.play_sound(False)
+                self.animate_widget(self.main_frame, "#2c3e50", "#c0392b", steps=8)
+                messagebox.showerror("Ошибка", "Нужно выбрать принтер в сейфовой комнате, время 5 минут и обязательную аутентификацию.")
+        
+        btn = tk.Button(self.main_frame, text="Проверить", command=check3, bg="#3498db", fg="white", font=("Arial", 12, "bold"))
+        btn.pack(pady=20)
+        hint_btn = tk.Button(self.main_frame, text="Подсказка", command=lambda: self.show_hint("Конфиденциальная печать требует защищённого принтера, быстрого удаления и аутентификации."), bg="#f39c12", fg="white")
+        hint_btn.pack(pady=5)
+    
+    # СЦЕНА 4: Маркировка и уничтожение (с анимированными кнопками)
+    def scene4(self):
+        tk.Label(self.main_frame, text="СЦЕНА 4: Маркировка и уничтожение", font=("Arial", 16, "bold"), fg="#ecf0f1", bg="#2c3e50").pack(pady=10)
+        tk.Label(self.main_frame, text="Действия с конфиденциальными документами:", font=("Arial", 12), fg="#bdc3c7", bg="#2c3e50").pack(pady=5)
+        
+        tk.Label(self.main_frame, text="1. Как маркировать конфиденциальный документ?", fg="white", bg="#2c3e50").pack(anchor=tk.W)
+        self.mark_var = tk.StringVar(value="")
+        marks = ["Только гриф 'Конфиденциально'", "Штамп с номером экземпляра", "Без маркировки"]
+        for m in marks:
+            tk.Radiobutton(self.main_frame, text=m, variable=self.mark_var, value=m, bg="#2c3e50", fg="white").pack(anchor=tk.W)
+        
+        tk.Label(self.main_frame, text="2. Что сделать с бракованной распечаткой?", fg="white", bg="#2c3e50").pack(anchor=tk.W, pady=(10,0))
+        self.destroy_var = tk.StringVar(value="")
+        destroys = ["Выбросить в мусор", "Использовать как черновик", "Уничтожить в шредере 3-й степени", "Сжечь"]
+        for d in destroys:
+            tk.Radiobutton(self.main_frame, text=d, variable=self.destroy_var, value=d, bg="#2c3e50", fg="white").pack(anchor=tk.W)
+        
+        def check4():
+            mark_ok = (self.mark_var.get() == "Штамп с номером экземпляра")
+            destroy_ok = (self.destroy_var.get() == "Уничтожить в шредере 3-й степени")
+            if mark_ok and destroy_ok:
+                self.play_sound(True)
+                self.animate_widget(self.main_frame, "#2c3e50", "#27ae60", steps=8)
+                messagebox.showinfo("Верно", "Маркировка и уничтожение выполнены правильно!")
+                self.next_scene()
+            else:
+                self.play_sound(False)
+                self.animate_widget(self.main_frame, "#2c3e50", "#c0392b", steps=8)
+                messagebox.showerror("Ошибка", "Нужен штамп с номером экземпляра и уничтожение в шредере 3-й степени.")
+        
+        btn = tk.Button(self.main_frame, text="Проверить", command=check4, bg="#3498db", fg="white", font=("Arial", 12, "bold"))
+        btn.pack(pady=20)
+        hint_btn = tk.Button(self.main_frame, text="Подсказка", command=lambda: self.show_hint("Каждый конфиденциальный документ должен иметь уникальный номер экземпляра, брак уничтожается в шредере с высокой степенью защиты."), bg="#f39c12", fg="white")
+        hint_btn.pack(pady=5)
+    
+    # СЦЕНА 5: Расследование инцидента с таблицей и анимацией
+    def scene5(self):
+        tk.Label(self.main_frame, text="СЦЕНА 5: Расследование утечки", font=("Arial", 16, "bold"), fg="#ecf0f1", bg="#2c3e50").pack(pady=10)
+        tk.Label(self.main_frame, text="Инцидент: Петров распечатал 'Отчет_КТ.pdf' и забыл на принтере в холле. Через 10 минут документ исчез.\nЖурнал печати:", font=("Arial", 11), fg="#bdc3c7", bg="#2c3e50").pack(pady=5)
+        
+        # Таблица с данными
+        columns = ("Время", "Пользователь", "Документ", "Принтер", "Результат")
+        tree = ttk.Treeview(self.main_frame, columns=columns, show="headings", height=6)
+        for col in columns:
+            tree.heading(col, text=col)
+            tree.column(col, width=140)
+        data = [
+            ("09:05", "Петров", "Отчет_КТ.pdf", "Холл", "Напечатан"),
+            ("09:07", "Иванов", "Отчет_КТ.pdf", "Холл", "Напечатан"),
+            ("09:10", "Сидорова", "Приказ_общий.docx", "Холл", "Напечатан"),
+            ("09:12", "Иванов", "Список.xlsx", "Холл", "Отменено"),
+            ("09:15", "Петров", "Счет.pdf", "Сейфовая", "Напечатан")
+        ]
+        for row in data:
+            tree.insert("", tk.END, values=row)
+        tree.pack(pady=10)
+        
+        tk.Label(self.main_frame, text="Кто из сотрудников распечатал тот же конфиденциальный файл сразу после Петрова?", fg="white", bg="#2c3e50").pack()
+        self.suspect_var = tk.StringVar()
+        suspects = ["Петров", "Иванов", "Сидорова", "Неизвестный"]
+        for s in suspects:
+            tk.Radiobutton(self.main_frame, text=s, variable=self.suspect_var, value=s, bg="#2c3e50", fg="white").pack(anchor=tk.W)
+        
+        def check5():
+            if self.suspect_var.get() == "Иванов":
+                self.play_sound(True)
+                self.animate_widget(self.main_frame, "#2c3e50", "#27ae60", steps=8)
+                messagebox.showinfo("Верно", "Иванов распечатал тот же файл через 2 минуты, хотя его роль не позволяла печатать КТ. Нарушитель найден!")
+                self.next_scene()
+            else:
+                self.play_sound(False)
+                self.animate_widget(self.main_frame, "#2c3e50", "#c0392b", steps=8)
+                messagebox.showerror("Ошибка", "Неверно. Посмотрите внимательно на время и документ в журнале.")
+        
+        btn = tk.Button(self.main_frame, text="Проверить", command=check5, bg="#3498db", fg="white", font=("Arial", 12, "bold"))
+        btn.pack(pady=20)
+        hint_btn = tk.Button(self.main_frame, text="Подсказка", command=lambda: self.show_hint("Обратите внимание на строку 09:07 — тот же документ, другой пользователь."), bg="#f39c12", fg="white")
+        hint_btn.pack(pady=5)
+
+if __name__ == "__main__":
+    root = tk.Tk()
+    game = SecurityGame(root)
+    root.mainloop()