Menu
Coddy logo textTech

Masquage d'informations

Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 30 sur 64.

Le masquage d'informations limite l'accès direct aux composants de l'objet, exigeant que toutes les interactions passent par des interfaces bien définies. Cela protège les données internes contre tout accès non autorisé.

Voici un exemple d'une classe avec différents niveaux de masquage d'informations :

class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Public - accessible directement
        self._balance = initial_balance       # Protégé - usage interne
        self.__account_number = "ACC123456"   # Privé - masqué de l'extérieur

Ajoutez des méthodes qui fournissent un accès contrôlé aux données cachées :

class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner
        self._balance = initial_balance
        self.__account_number = "ACC123456"
        
    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
            return True
        return False
    
    def withdraw(self, amount):
        if amount > 0 and amount <= self._balance:
            self._balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self._balance
    
    def get_account_info(self):
        # Moyen sûr d'afficher des données privées partielles
        return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"

Utilisez la classe via son interface publique :

account = BankAccount("Alice", 1000)

Accédez directement aux données publiques :

print(account.owner)  # Alice - accès public OK

Utilisez des méthodes contrôlées pour les données protégées :

print(account.get_balance())  # 1000 - accès contrôlé
account.deposit(500)
print(account.get_balance())  # 1500 - solde modifié en toute sécurité

Essayez d'accéder aux données cachées :

print(account.get_account_info())  # Propriétaire : Alice, Compte : ***3456
# print(account.__account_number)  # AttributeError - caché

L'attribut privé subit un masquage de nom (name-mangling) mais reste techniquement accessible :

# Cela fonctionne mais viole le principe de masquage d'informations :
print(account._BankAccount__account_number)  # ACC123456

Sortie :

Alice
1000
1500
Owner: Alice, Account: ***3456
ACC123456

Point clé : Le masquage d'informations protège les données internes en les rendant privées ou protégées, puis en fournissant un accès contrôlé via des méthodes publiques. Cela empêche la manipulation directe des données sensibles et garantit l'intégrité des données grâce à la validation dans les méthodes d'accès.

challenge icon

Défi

Moyen

Dans ce défi, vous allez implémenter un système de messagerie sécurisé avec des tests complets pour valider votre solution.

Vous devez modifier securemessenger.py pour implémenter la classe SecureMessenger en suivant les principes de masquage d'informations. Le fichier contient des commentaires TODO détaillés pour guider votre implémentation.

Les exigences clés incluent :

  • Une encapsulation appropriée des identifiants et des messages
  • Une authentification avant d'autoriser les opérations sur les messages
  • Une surveillance de la sécurité via le suivi des tentatives de connexion
  • Des messages de retour précis comme spécifié dans les TODO

Aide-mémoire

Le masquage d'informations restreint l'accès direct aux composants d'un objet via des modificateurs d'accès :

  • public - accessible directement (pas de tiret bas)
  • _protected - utilisation interne (tiret bas simple)
  • __private - masqué de l'extérieur (double tiret bas)
class BankAccount:
    def __init__(self, owner, initial_balance):
        self.owner = owner                    # Public
        self._balance = initial_balance       # Protégé
        self.__account_number = "ACC123456"   # Privé

Fournissez un accès contrôlé via des méthodes publiques :

def get_balance(self):
    return self._balance

def deposit(self, amount):
    if amount > 0:
        self._balance += amount
        return True
    return False

Les attributs privés subissent un masquage de nom (name mangling) mais restent accessibles :

# Viole le masquage d'informations mais fonctionne :
print(account._BankAccount__account_number)

Essayez vous-même

from securemessenger import SecureMessenger

# Gestionnaire de cas de test
test_case = input()
if test_case == "default_test":
    # Cas de test standard du problème original
    messenger = SecureMessenger("user1")
    
    # Essayer d'ajouter des messages avant la connexion
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Tentative de connexion avec un mauvais mot de passe
    print(messenger.login("wrong_pass"))
    
    # Connexion avec le bon mot de passe
    print(messenger.login("secure123"))
    
    # Ajouter des messages après une connexion réussie
    print(messenger.add_message("Hello World!"))
    print(messenger.add_message("Secure Message"))
    
    # Récupérer les messages
    print(messenger.get_messages())
    
    # Vérifier les tentatives de connexion
    print(messenger.get_login_attempts())
elif test_case == "custom_password":
    # Test avec un mot de passe personnalisé
    messenger = SecureMessenger("admin", "admin123")
    print(messenger.login("wrong_password"))
    print(messenger.login("admin123"))
    print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
    # Tester plusieurs tentatives de connexion
    messenger = SecureMessenger("user2")
    print(messenger.login("attempt1"))
    print(messenger.login("attempt2"))
    print(messenger.login("attempt3"))
    print(messenger.login("secure123"))
    print(messenger.get_login_attempts())
elif test_case == "message_management":
    # Tester la gestion des messages
    messenger = SecureMessenger("user3")
    print(messenger.login("secure123"))
    
    # Ajouter plusieurs messages
    messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
    for msg in messages:
        print(messenger.add_message(msg))
    
    # Vérifier tous les messages
    print(messenger.get_messages())
elif test_case == "empty_messages":
    # Tester le cas des messages vides
    messenger = SecureMessenger("user4")
    print(messenger.login("secure123"))
    print(messenger.get_messages())
elif test_case == "access_without_login":
    # Tester l'accès sans connexion
    messenger = SecureMessenger("user5")
    print(messenger.add_message("Unauthorized message"))
    print(messenger.get_messages())
elif test_case == "attribute_privacy":
    # Tester la confidentialité des attributs
    messenger = SecureMessenger("user6")
    
    # Attribut public
    print(f"Public username: {messenger.username}")
    
    # Attributs privés - ceux-ci devraient lever une exception AttributeError
    try:
        print(messenger.__password)
    except AttributeError as e:
        print("Password is private: AttributeError")
    
    try:
        print(messenger.__messages)
    except AttributeError as e:
        print("Messages are private: AttributeError")
    
    try:
        print(messenger.__login_attempts)
    except AttributeError as e:
        print("Login attempts are private: AttributeError")
    
    try:
        print(messenger.__is_logged_in)
    except AttributeError as e:
        print("Login status is private: AttributeError")
elif test_case == "login_logout_sequence":
    # Ce test nécessite d'étendre la classe avec une méthode de déconnexion
    # Pour les besoins du test, nous allons créer une sous-classe avec une fonctionnalité de déconnexion
    class ExtendedMessenger(SecureMessenger):
        def logout(self):
            self._SecureMessenger__is_logged_in = False
            return "Logged out successfully"
    
    messenger = ExtendedMessenger("user7")
    print(messenger.login("secure123"))
    print(messenger.add_message("Test message"))
    print(messenger.get_messages())
    print(messenger.logout())
    print(messenger.get_messages())
elif test_case == "stress_test":
    # Test de charge avec de nombreux messages
    messenger = SecureMessenger("user8")
    print(messenger.login("secure123"))
    
    # Ajouter 100 messages
    for i in range(1, 101):
        messenger.add_message(f"Message {i}")
    
    # Vérifier le nombre de messages
    messages = messenger.get_messages()
    newline_char = '\n'  # Stocker le caractère de nouvelle ligne dans une variable
    message_count = len(messages.split(newline_char))
    print(f"Added 100 messages. Retrieved {message_count} messages.")
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming