بسبب التغيير الأخير في طلب السحب #43042، أصبح مسار /u/check_username.json مقيدًا بمعدل 10 طلبات في الدقيقة لكل عنوان IP.
يبدو أن هذا التسبب في تراجع (Regression) في سير عمل التسجيل الطبيعي.
عند إنشاء حساب جديد، يقوم Discourse تلقائيًا بفحص توفر اسم المستخدم. لا يحتاج المستخدم إلى إرسال النموذج بشكل متكرر للوصول إلى هذا الحد. فمجرد إدخال عنوان البريد الإلكتروني واسم المستخدم، والتوقف مؤقتًا أثناء الكتابة، أو تغيير اسم المستخدم، أو تصحيحه يمكن أن يؤدي إلى إرسال عدة طلبات إلى /u/check_username.json.
بمجرد الوصول إلى الحد الأقصى، يعرض نموذج التسجيل الرسالة التالية:
لقد قمت بهذا الإجراء مرات عديدة جدًا، يرجى المحاولة مرة أخرى لاحقًا.
يظهر الخطأ مباشرة أسفل حقل اسم المستخدم ويمنع المستخدم فعليًا من المتابعة حتى ينتهي سريان مُقيّد المعدل (Rate Limiter).
لا يوجد أي مؤشر على المدة التي يجب على المستخدم الانتظار فيها، ومن وجهة نظر المستخدم، يبدو وكأن اسم المستخدم المختار أو نموذج التسجيل معطل.
خطوات إعادة الإنتاج
- افتح نموذج التسجيل كمستخدم مجهول.
- أدخل عنوان بريد إلكتروني صالحًا.
- أدخل اسم المستخدم وعدّله عدة مرات، مع السماح بفحص توفر اسم المستخدم بين كل تغيير وآخر.
- واصل العملية حتى يتم استدعاء
/u/check_username.jsonأكثر من 10 مرات خلال دقيقة واحدة. - يبدأ حقل اسم المستخدم في عرض خطأ مُقيّد المعدل:
لقد قمت بهذا الإجراء مرات عديدة جدًا، يرجى المحاولة مرة أخرى لاحقًا.
السلوك المتوقع
لا ينبغي أن يُحظر مستخدم عادي يكمل أو يصحح نموذج التسجيل بواسطة حد معدل داخلي محفّز بفحوصات توفر اسم المستخدم التلقائية.
إذا كان تقييد المعدل مطلوبًا لمنع سوء الاستخدام، فينبغي أن يتدهور تفاعل المستخدم في التسجيل بشكل سلس (Gracefully) بدلاً من عرض خطأ تقييد المعدل ومنع إنشاء الحساب.
السلوك الفعلي
يتلقى المستخدم خطأ تحقق مضمّنًا في حقل اسم المستخدم ولا يمكنه المتابعة بشكل طبيعي حتى ينتهي سريان حد المعدل.
التغيير ذو الصلة
يبدو أن هذا قد تم تقديمه بواسطة:
طلب السحب #43042 – DEV: تقييد معدل طلبات check_username لكل IP
يستخدم التنفيذ الحالي:
RateLimiter.new(
current_user,
"check-username-#{request.remote_ip}",
10,
1.minute
).performed!
يمكن لواجهة التسجيل نفسها توليد عدة فحوصات لاسم المستخدم، لذا يمكن الوصول إلى حد 10 طلبات في الدقيقة أثناء التفاعل المشروع.
قد يكون هذا أيضًا أكثر إشكالية للمستخدمين الذين يكونون خلف عناوين IP عامة أو عناوين NAT مشتركة، لأن المُقيّد يعتمد على عنوان IP بدلاً من الجلسة.
ملاحظة إضافية
يوجد أيضًا مُقيّد بمعدل 10 طلبات/دقيقة/IP لـ check_email، ولكن عند تجاوز هذا الحد، يعيد استجابة ناجحة بدلاً من إظهار خطأ تقييد المعدل للمستخدم.
لذلك، قد يكون من المنطقي أن يتصرف check_username بشكل مشابه، أو بديلاً عن ذلك:
-
زيادة الحد الأقصى؛
-
جعله قابلًا للتكوين؛
-
تجنب احتساب طلبات اقتراح اسم المستخدم/التحقق التلقائي في نفس الدلو (Bucket)؛
-
أو التعامل مع تقييد المعدل على جانب العميل دون عرقلة سير عمل التسجيل.
يمكنني إعادة إنتاج هذا الخطأ على تثبيت Discourse حالي، بما في ذلك https://try.discourse.org/ بعد التغيير من طلب السحب #43042.
