بايثون بالمثال 16: إنشاء كلمة مرور عشوائية باستخدام secrets

إنشاء مولد كلمات مرور عشوائية باستخدام secrets في بايثون

هل احتجت يومًا إلى كلمة مرور طويلة مختلفة لكل حساب، لكنك لم تعرف كيف تنشئها دون اختيار كلمات سهلة أو نمط متكرر؟ في هذا المثال سنبني برنامجًا صغيرًا ينشئ كلمة مرور عشوائية من الحروف والأرقام والرموز باستخدام مكتبة secrets المدمجة في بايثون.

هذا التطبيق مناسب للمبتدئ لأنه يجمع بين الدوال، النصوص، القوائم، الشروط، الحلقات، إدخال المستخدم، ومعالجة الأخطاء. والأهم أنه يوضح فرقًا عمليًا مهمًا: ليست كل العشوائية مناسبة للمهام المرتبطة بكلمات المرور.

{alertInfo} الفكرة ببساطة: سنكوّن مجموعة من الحروف الصغيرة والكبيرة والأرقام والرموز، ثم نختار منها عناصر عشوائية باستخدام secrets.choice()، ونرتبها بطريقة عشوائية قبل عرض كلمة المرور النهائية.

{getToc} $title={محتوى المقال}

ماذا سنتعلم من هذا المثال؟

  • لماذا نستخدم secrets بدل random عند إنشاء كلمات المرور.
  • استخدام string.ascii_lowercase وstring.ascii_uppercase وstring.digits.
  • اختيار رمز عشوائي باستخدام secrets.choice().
  • إنشاء دالة تقبل طول كلمة المرور وتعيد كلمة جاهزة.
  • ضمان وجود حرف صغير وحرف كبير ورقم ورمز في النتيجة.
  • قراءة طول كلمة المرور من المستخدم والتحقق من الإدخال.
  • التعامل مع ValueError عند إدخال قيمة غير صحيحة.

لماذا لا نستخدم random لكلمات المرور؟

مكتبة random رائعة للألعاب والمحاكاة والاختيارات التعليمية، مثل رمي حجر نرد أو خلط أسئلة اختبار. لكن عندما تكون العشوائية مرتبطة بكلمات مرور أو رموز تسجيل دخول أو بيانات حساسة، استخدم secrets.

توثيق بايثون الرسمي يوصي باستخدام secrets بدل مولد الأرقام شبه العشوائي الافتراضي في random عند التعامل مع كلمات المرور والرموز الأمنية، لأن secrets يعتمد على مصدر عشوائية مناسب لهذا النوع من الاستخدام.

المكتبة استخدام مناسب هل نستخدمها لكلمة مرور؟
random الألعاب، المحاكاة، أسئلة عشوائية، أمثلة تدريبية. لا، ليست الخيار المناسب لكلمات المرور الفعلية.
secrets كلمات المرور، الرموز المؤقتة، مفاتيح الاسترداد، المعرفات الصعبة التخمين. نعم، استخدمها لهذا الغرض.

راجع درس أساسيات بايثون 28: شرح مكتبة random لفهم استخدامات random المناسبة، ثم اعتبر secrets خيارك عندما يكون الموضوع متعلقًا بكلمات المرور.

الفرق بين secrets وrandom عند إنشاء كلمات المرور في بايثون

مكونات كلمة المرور

سنستخدم أربع مجموعات من الرموز:

  • الحروف الصغيرة مثل a وb.
  • الحروف الكبيرة مثل A وB.
  • الأرقام مثل 0 و1.
  • الرموز مثل ! و@ و#.

توفر مكتبة string مجموعات جاهزة للحروف والأرقام، لذلك لا نحتاج إلى كتابة الأبجدية يدويًا:

import string

lowercase_letters = string.ascii_lowercase
uppercase_letters = string.ascii_uppercase
digits = string.digits
symbols = "!@#$%^&*_-+="

print(lowercase_letters)
print(uppercase_letters)
print(digits)
print(symbols)

استخدمنا قائمة رموز صغيرة ومحددة بدل كل الرموز الممكنة، لأن بعض المواقع قد لا تقبل رموزًا معينة، وقد يكون بعضها محيرًا عند النسخ واللصق. تستطيع تعديل مجموعة symbols لاحقًا بما يناسبك.

دمج الحروف الكبيرة والصغيرة والأرقام والرموز لإنشاء كلمة مرور عشوائية

أول نسخة بسيطة من مولد كلمة المرور

هذه النسخة تنشئ كلمة من 16 رمزًا بالاختيار من مجموعة واحدة كبيرة:

import secrets
import string

characters = (
    string.ascii_lowercase
    + string.ascii_uppercase
    + string.digits
    + "!@#$%^&*_-+="
)

password = "".join(
    secrets.choice(characters)
    for _ in range(16)
)

print("كلمة المرور الجديدة:", password)

سيعطيك البرنامج كلمة مختلفة غالبًا في كل تشغيل، مثل:

كلمة المرور الجديدة: nR7@eQ4s!V2kL9#x

لكن هذه النسخة لا تضمن ظهور كل نوع من الرموز. من الممكن، رغم أن ذلك غير شائع، أن تتكون النتيجة من حروف وأرقام فقط دون رمز. لذلك سنحسن البرنامج في الخطوة التالية.

بناء دالة تضمن تنوع الرموز

سننشئ دالة تطلب طول كلمة المرور، ثم تضع في البداية رمزًا واحدًا على الأقل من كل مجموعة:

  • حرف صغير واحد على الأقل.
  • حرف كبير واحد على الأقل.
  • رقم واحد على الأقل.
  • رمز واحد على الأقل.

بعد ذلك نكمل بقية الطول المطلوب من كل المجموعات، ثم نخلط ترتيب العناصر. هكذا لا تظهر كلمة المرور دائمًا بالحرف الصغير ثم الكبير ثم الرقم ثم الرمز بالترتيب نفسه.

import secrets
import string


def generate_password(length):
    if length < 12:
        raise ValueError(
            "اختر طولًا لا يقل عن 12 رمزًا."
        )

    lowercase_letters = string.ascii_lowercase
    uppercase_letters = string.ascii_uppercase
    digits = string.digits
    symbols = "!@#$%^&*_-+="

    all_characters = (
        lowercase_letters
        + uppercase_letters
        + digits
        + symbols
    )

    password_characters = [
        secrets.choice(lowercase_letters),
        secrets.choice(uppercase_letters),
        secrets.choice(digits),
        secrets.choice(symbols),
    ]

    remaining_length = length - len(password_characters)

    for _ in range(remaining_length):
        password_characters.append(
            secrets.choice(all_characters)
        )

    secure_random = secrets.SystemRandom()
    secure_random.shuffle(password_characters)

    return "".join(password_characters)


password = generate_password(16)
print("كلمة المرور الجديدة:", password)

هذه الدالة تستخدم return لإرجاع كلمة المرور، ثم نخزنها في المتغير password. راجع درس أساسيات بايثون 14: شرح return في الدوال إن لم تكن مرتاحًا لفكرة إرجاع القيم.

دالة بايثون لإنشاء كلمة مرور عشوائية مع طول محدد

شرح الدالة خطوة بخطوة

1. التحقق من الطول

if length < 12:
    raise ValueError(
        "اختر طولًا لا يقل عن 12 رمزًا."
    )

الشرط يمنع تمرير طول قصير جدًا في هذا المثال التعليمي. الرقم 12 ليس قاعدة عامة لكل المواقع، لأن لكل خدمة قواعدها الخاصة، لكنه حد عملي مناسب للبرنامج الذي نبنيه هنا.

2. إضافة رمز من كل مجموعة

password_characters = [
    secrets.choice(lowercase_letters),
    secrets.choice(uppercase_letters),
    secrets.choice(digits),
    secrets.choice(symbols),
]

بهذه الطريقة نضمن أن كلمة المرور تحتوي على كل الأنواع التي اخترناها. لاحظ أن secrets.choice() تأخذ عنصرًا واحدًا عشوائيًا من النص أو القائمة التي تمررها إليها.

3. إكمال باقي الرموز

remaining_length = length - len(password_characters)

for _ in range(remaining_length):
    password_characters.append(
        secrets.choice(all_characters)
    )

لأننا أضفنا أربعة رموز مسبقًا، نطرح 4 من الطول المطلوب ضمنيًا عبر len(password_characters). إذا اخترت طول 16، ستضيف الحلقة 12 رمزًا إضافيًا.

4. خلط الترتيب

secure_random = secrets.SystemRandom()
secure_random.shuffle(password_characters)

لو لم نخلط القائمة، قد تبدأ كل كلمة مرور بحرف صغير ثم حرف كبير ثم رقم ثم رمز. الخلط يجعل مواضع الرموز متنوعة بدل ترتيب ثابت.

نسخة تفاعلية تطلب الطول من المستخدم

الآن سنحوّل المثال إلى برنامج صغير يطلب من المستخدم طول كلمة المرور. سنستخدم try وexcept حتى لا يتوقف البرنامج إذا كتب المستخدم نصًا مثل عشرة بدل رقم.

import secrets
import string


def generate_password(length):
    if length < 12:
        raise ValueError(
            "اختر طولًا لا يقل عن 12 رمزًا."
        )

    lowercase_letters = string.ascii_lowercase
    uppercase_letters = string.ascii_uppercase
    digits = string.digits
    symbols = "!@#$%^&*_-+="

    all_characters = (
        lowercase_letters
        + uppercase_letters
        + digits
        + symbols
    )

    password_characters = [
        secrets.choice(lowercase_letters),
        secrets.choice(uppercase_letters),
        secrets.choice(digits),
        secrets.choice(symbols),
    ]

    for _ in range(
        length - len(password_characters)
    ):
        password_characters.append(
            secrets.choice(all_characters)
        )

    secure_random = secrets.SystemRandom()
    secure_random.shuffle(password_characters)

    return "".join(password_characters)


try:
    length = int(
        input("أدخل طول كلمة المرور، مثل 16: ")
    )

    password = generate_password(length)

    print("كلمة المرور الجديدة:")
    print(password)

except ValueError as error:
    print(f"إدخال غير صالح: {error}")

شغّل البرنامج، ثم جرّب هذه الحالات:

الإدخال ما المتوقع؟
16 ينشئ البرنامج كلمة مرور طولها 16 رمزًا.
8 يظهر تنبيه يطلب طولًا لا يقل عن 12.
abc يظهر تنبيه لأن int() لا يستطيع تحويل النص إلى رقم.
{alertWarning} تنبيه مهم: لا تضع كلمة مرور حقيقية داخل ملف مشروعك، ولا ترفعها إلى GitHub، ولا تسجلها داخل print أو logging في تطبيق حقيقي. استخدم مدير كلمات مرور موثوقًا لحفظ الكلمات الجديدة.

التحقق من طول كلمة المرور وإدخال المستخدم في برنامج بايثون

فحص بسيط لقواعد كلمة المرور

يمكننا كتابة دالة تعليمية تفحص هل النص يحتوي على حرف صغير وكبير ورقم ورمز. هذه الدالة مفيدة لفهم الشروط، لكنها لا تقيس كل جوانب أمان كلمة المرور ولا تغني عن سياسات الحماية في المواقع الحقيقية.

def check_password_rules(password):
    has_lowercase = any(char.islower() for char in password)
    has_uppercase = any(char.isupper() for char in password)
    has_digit = any(char.isdigit() for char in password)
    has_symbol = any(
        char in "!@#$%^&*_-+="
        for char in password
    )

    return (
        len(password) >= 12
        and has_lowercase
        and has_uppercase
        and has_digit
        and has_symbol
    )


test_password = "aB7!samplePass"

if check_password_rules(test_password):
    print("كلمة المرور تحقق قواعد المثال.")
else:
    print("كلمة المرور لا تحقق قواعد المثال.")

أخطاء شائعة في مولد كلمات المرور

1. استخدام random مع كلمة مرور فعلية

قد يعمل الكود، لكن اختيار المكتبة ليس مناسبًا للغرض. استخدم secrets عندما تنشئ كلمات مرور أو رموزًا يصعب تخمينها.

2. اختيار كلمات أو أنماط سهلة التخمين

كلمة مثل Ali123 أو Password2026 قد تكون سهلة التذكر، لكنها ليست فكرة جيدة لكلمة مرور فعلية. الهدف من البرنامج هو إنشاء نص مختلف وغير متوقع، وليس بناء كلمة مألوفة.

3. تثبيت الترتيب نفسه للرموز

إضافة حرف صغير ثم كبير ثم رقم ثم رمز أمر جيد لضمان التنوع، لكن يجب خلط القائمة قبل تحويلها إلى نص نهائي. لهذا استخدمنا SystemRandom().shuffle().

4. قبول طول قصير جدًا

لا تجعل الدالة تقبل أي رقم دون فحص. في مثالنا نرفض القيم الأقل من 12 حتى يظهر للمستخدم سبب الرفض بدل توليد كلمة قصيرة جدًا دون تنبيه.

5. طباعة أو حفظ كلمة المرور في مكان عام

في مثال تعليمي على جهازك، يمكن عرض الكلمة في Terminal. أما في تطبيق حقيقي فلا تسجل كلمات المرور في ملفات السجل، ولا تضعها في مستودع GitHub أو لقطة شاشة أو رسالة عامة.

تطوير المشروع خطوة بخطوة

  • أضف خيارًا يتيح للمستخدم تحديد هل يريد الرموز أم لا.
  • أضف خيارًا لاستبعاد الرموز المتشابهة مثل O و0 وl و1.
  • أنشئ قائمة كلمات مرور متعددة بدل كلمة واحدة.
  • اكتب اختبارًا بسيطًا يتأكد أن الدالة تعيد طولًا صحيحًا.
  • حوّل البرنامج إلى أداة سطر أوامر باستخدام argparse بعد أن تتعلم أساسيات برامج سطر الأوامر.

روابط داخلية مفيدة من بايثون العرب

الخلاصة

  • استخدم secrets بدل random عند إنشاء كلمات مرور أو رموز حساسة.
  • تساعد مكتبة string على الحصول على الحروف والأرقام دون كتابتها يدويًا.
  • ضع رمزًا واحدًا على الأقل من كل مجموعة تريدها، ثم أضف بقية الرموز عشوائيًا.
  • اخلط ترتيب الرموز قبل تحويل القائمة إلى نص نهائي.
  • تحقق من طول الإدخال وتعامل مع ValueError بدل توقف البرنامج.
  • لا تحفظ كلمة مرور حقيقية في الكود أو ملفات المشروع أو السجلات.
{alertSuccess} قاعدة عملية: كلمة المرور الجيدة لا تحتاج إلى أن تكون سهلة الحفظ؛ تحتاج إلى أن تكون طويلة وفريدة ومخزنة في مدير كلمات مرور موثوق، مع تفعيل التحقق بخطوتين عندما يكون متاحًا.

مصادر رسمية للتوسع

أسئلة شائعة

هل أحتاج إلى تثبيت مكتبة secrets عبر pip؟

لا. secrets مكتبة قياسية تأتي مع بايثون الحديثة، لذلك يكفي استدعاؤها باستخدام import secrets.

هل يمكنني استخدام random بدل secrets؟

استخدم random في الألعاب والتمارين والمحاكاة. أما لكلمات المرور أو الرموز الأمنية فاستخدم secrets لأنه مخصص لهذا النوع من العشوائية.

لماذا لا أستخدم كل رموز string.punctuation؟

يمكنك ذلك، لكن بعض المواقع لا تقبل جميع الرموز، وبعضها قد يكون مزعجًا عند النسخ أو غير واضح في بعض الخطوط. لذلك استخدمنا مجموعة صغيرة يمكنك تعديلها حسب الحاجة.

هل طول 12 مناسب دائمًا؟

هو حد تعليمي اختاره المثال، وليس قاعدة ثابتة لكل موقع. اتبع متطلبات الخدمة التي تستخدمها، ويفضل في العموم اختيار كلمات مرور أطول وفريدة لكل حساب.

هل برنامج مولد كلمات المرور يغني عن مدير كلمات المرور؟

لا. البرنامج ينشئ كلمة مرور فقط. مدير كلمات المرور يساعدك على حفظ كلمات مختلفة وطويلة لكل حساب دون الحاجة إلى كتابتها في ملف أو تذكرها يدويًا.

إرسال تعليق

أحدث أقدم