سؤال

أقوم بإنشاء موقع PHP الذي ينطوي على المستخدمين يوقعون، وأتساءل عن أفضل الممارسات لرموز "تأكيد البريد الإلكتروني".

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

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");

حيث يشير Timestamp $ إلى وقت إنشاء المستخدم. على العموم، كنت سعيدا جدا بهذا، ولكن بعد ذلك، يجب أن أفكر، هل هذا آمن بما فيه الكفاية؟ وماذا عن إمكانية الاصطدام؟ وأحتاج أيضا إلى إنشاء رموز لإعادة تعيين كلمة المرور، وما إلى ذلك. إذا كنت قد استخدمت منهجية مشابهة، فقد يؤدي التصادم إلى إعادة تعيين مستخدم واحد عن غير قصد كلمة مرور مستخدم آخر. وهذا ليس جيدا.

فكيف تفعل هذه الأشياء؟ كانت أفكاري جدول بالتنسيق التالي:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)

حيث "النوع" سيكون 1 أو 2 أو 3 معنى "التنشيط" أو "تغيير البريد الإلكتروني" أو "إعادة تعيين كلمة المرور". هل هذه طريقة جيدة للقيام بذلك؟ هل لديك طريقة أفضل؟

باستخدام طريقة مماثلة لما ورد أعلاه، هل يمكنني حذف أي شيء تلقائيا أكثر من يومين دون استخدام Cron-Jobs؟ مضيفي (nearlyfreeSpeech.net) لا يدعمها. إذا كان ذلك ممكنا على الإطلاق، أود تجنب امتلاك وظيفة Cron على مضيف خارجي يعمل على برنامج نصي يقوم بحذف الأشياء، لأن هذا مجرد فوضوي = ص.

شكرا!
مالا

تحديث:
لتوضيح: لقد أدركت الطريقة الوحيدة لتذهب بشكل آمن وأمان حول هذه المهمة هي باستخدام قاعدة بيانات، وهو ما كانت الوظيفة الأصلية تحاول تجنبها. سؤالي هو كيف ينبغي تنظيم الجدول (أو الجداول؟). اقترح شخص ما أن أفعل بعيدا مع CODEPK وأصنع الكود A PK. لذلك باختصار، سؤالي هو: هل هذا ما تفعله؟

هل كانت مفيدة؟

المحلول

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

  1. كمفتاح يستخدم لإرسال رسائل البريد الإلكتروني للتحقق إلى المستخدم
  2. كإجراء يستخدم لروابط إعادة تعيين كلمة المرور

بالطبع سيكون هناك العديد من المناسبات الأخرى التي ستفكر فيها في استخدام مثل هذا البناء.

بادئ ذي بدء، يجب عليك دائما استخدام نوع من الملح المخفي وأنك تعرف فقط. لاحظ أن هذا الملح يجب أن يكون مختلفا لكل مستخدم. الملح يمكن حسابه على سبيل المثال sha256(something random). وبعد يجب بعد ذلك تخزين هذا الملح في قاعدة البيانات جنبا إلى جنب مع اسم المستخدم وكلمة المرور (الفحص بالملح).

ما سأفعله عند إرسال رابط إعادة تعيين كلمة المرور هو إنشاء ملح آخر (لا تعطي الوصول إلى أي شيء تجزئ مع الملح الخاص بك. إنه يعرف كلمة مروره، لذلك باستخدام BruteForce يمكنه معرفة الملح الخاص بك). الملح الآخر، الذي هو أساسا هو مجرد تجزئة سلسلة عشوائية (قد ترغب في الذهاب إلى MD5 هنا، كما ذكرت أن الطول مشكلة)، إذا قمت بالاحتفاظ بها في قاعدة البيانات الخاصة بك.

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

ما يغلي بشكل أساسي إلى:

  • Hash كلمات مرور المستخدمين الخاصة بك باستخدام ملح فريد من نوع المستخدم (و ربما ملح عالمي، سر).
  • توليد مفتاح عن طريق التجزئة عددا من مصادر عشوائية أو كاذبة مثل الطوابع الزمنية، mt_rand() أو حتى random.org إذا كنت تريد حقا أشياء عشوائية.
  • لا تستخدم الملح العالمي الخاص بك أو الملح الخاص بك فريد من نوعه للمستخدم تجزئة أي شيء يحصل عليه المستخدم الوصول إليه، بما في ذلك مفاتيح إعادة تعيين كلمة المرور، مفاتيح التنشيط، إلخ.

من فضلك لا أكون خبيرا أمنيا، وربما نسيت عددا من الأشياء، وقد ذكرت بعض الأشياء الممارسات السيئة للغاية. فقط بلدي 5 سنتات ؛-)

نصائح أخرى

لماذا استخدام أي من بيانات المستخدم كأساس لمفتاح التفويض؟

أفترض أنك تقوم بتخزين البيانات المنشطة في قاعدة بيانات، فلماذا لا تضيف مجرد سجل إضافي هو ببساطة مفتاح عشوائي (ربما md5'ed UNIQID. مع بعض التلاعب الإضافي) ثم تحقق من ذلك؟

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

يجب عليك استخدام نوع من وظيفة التجزئة المفكنية أو Mac بشكل مثالي، مما يشتمل على مفتاح سري معروف لك فقط.

لماذا لا تجعل الفهرس فريد من التعليمات البرمجية؟ لذلك لن يكون هناك collsiss؟

أيضا، إذا كنت لا تحتاج إلى إنشاء التجزئة من إدخال المستخدم ومطابقتها إلى تجزئة قاعدة البيانات (تأكيد البريد الإلكتروني وإعادة تعيين كلمة المرور وما إلى ذلك) - يمكنك إضافة سلسلة عشوائية إلى جسم التجزئة، مثلmd5('xxx'.$username.'xxx'.time().'xxx'.rand())

لماذا لا تطلب من المستخدم إدخال اسم المستخدم الخاص بهم و كودها، وبالتالي القضاء على أي مشكلة مع الاصطدام؟ أنت لا تفقد أي شيء أمن حكيمة لأنك ما زلت تطلب المفتاح الذي سيقومون به من البريد الإلكتروني، لكنك تمنعهم قادرين على إعادة تعيين كلمات مرور المستخدمين الآخرين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top