PDA

View Full Version : یک پروژهء سیستم رجیستر و لاگین بازمتن



eshpilen
سه شنبه 22 فروردین 1391, 11:16 صبح
توجه!

آخرین نسخهء این پروژه را از آخرین پست بنده در این تاپیک که دارای فایل ضمیمه میباشد دانلود کنید.
نسخهء ضمیمه شده به این پست نسخهء اولیه/قدیمی میباشد.


-----------------------------------

میتونید این پروژه رو از فایل ضمیمهء این پست دانلود کنید.
ویرایش: این پروژه در github هم وارد شد: https://github.com/ferchang/reg8log

چند ماه بود داشتم روی این پروژه شخصی کار میکردم.
این یک سیستم رجیستر و لاگین است که سعی کردم از نظر امکانات و امنیت درحد قابل توجهی باشه.
البته بیس این پروژه یک پروژهء مشابه خیلی قدیمی تر بود که چند سال پیش ارائه کرده بودم، اما تغییرات و افزوده ها بسیار زیاد هستن و این یک پروژهء خیلی کامل تر و امن تر از اون قبلی است.

===================

این پروژه تحت مجوز نرم افزار آزاد GPL نسخهء 2 یا بالاتر ارائه میشود.

===================

البته این پروژه هنوز در مراحل آزمایشی است و بنابراین معلوم نیست چقدر و چه نوع باگهایی ممکنه از توش دربیاد. هنوز نسخهء فارسی اون رو هم درست نکردم و این نسخه انگلیسی هست که برای بررسی و فیدبک و گزارش باگ و هرگونه پیشنهاد و انتقاد و ایده ای منتشرش میکنم، چون مراحل تست و توسعهء انفرادی تا همینجا بصورت بهینه پیش رفته و بعد از این بهتره پروژه عمومی مطرح بشه تا کار بیهوده و دوباره کاری صورت نگیره.
البته اینکه میگم انگلیسی منظور این نیست که نشه با زبان فارسی ازش استفاده کرد. فقط منظورم اینه که تمام نوشته ها و پیامهاش به زبان انگلیسی هستن.

===================

دربارهء پرفورمنس این برنامه هیچ ادعایی نمیکنم و قولی نمیدم. این یه پروژهء شخصی بوده و خواستم تمرکز و وقت و انرژی خودم رو روی کامل و دقیق بودن الگوریتم و امنیتش بذارم و در ضمن امکانات کافی داشته باشه. اساسا اون رو برای سایتهای کوچک و معمولی که تعداد کاربر و ترافیک خیلی زیادی ندارن درنظر گرفتم (*). خواستم فرق و برتری این پروژه با بقیه پروژه ها در مسائل امنیتی و کمال و دقت منطقش باشه و بیشتر منابع خودم رو به این پارامترها اختصاص دادم.
بهرحال پیاده سازی امنیت و منطق کامل و دقیق هزینه داره و حجم و پیچیدگی بیشتر کد که موجب کاهش پرفورمنس میشه. اما اینکه این هزینه دقیقا چقدره و این پروه تا چه مقیاسی قابل استفاده است نمیدونم؛ باید در عمل تجربه بشه.
البته بنده بهینه سازیهایی رو که بنظرم واقعا درشت و مهم بودن و پیاده سازی اونها کار و پیچیدگی زیادی نداشت سعی کردم انجام بدم، ولی احتمالا بازم میشه و شاید در نهایت از نظر عملی لازم باشه بهینه سازیهای دیگری که ممکنه شامل مقداری تغییرات در طراحی دیتابیس و بعضی زیرسیستم ها هم باشه انجام بشن. بهرحال این اولین کار نسبتا گستردهء بنده است و هنوز باید آزمایش و بررسی بشه.
بعضی چیزها شاید بنظرتون عجیب بیاد، مثلا اینکه چرا از یک رشتهء رندوم، بجای فیلد عددی auto_increment، برای uid استفاده شده (که افرادی بهم گفتن از نظر پرفورمنس اصلا جالب نیست). علتش توجه بالا به امنیت بوده و جلوگیری از نشت هرگونه اطلاعات و اتفاقات و سوء استفاده های آینده در زمینهء امنیت (توضیحش حالا بماند که از حوصلهء این توضیحات کلی خارج است). ولی بهرحال اگر در عمل لازم باشه میشه این قبیل چیزها رو تغییر داد یا مواردی رو که میخوایم به دیتابیس و بقیهء برنامه اضافه کنیم.

بنده کلا از این روش و توصیهء حداقل بعضی از برنامه نویسان حرفه ای استفاده میکنم که وقت و انرژی خودم رو روی بهینه سازیهای جزیی صرف نکرده و بخاطر بهینه سازیهای جزیی کد رو بیخودی حجیمتر و پیچیده تر نمیکنم، مگر اینکه در عمل مشکل پرفورمنس جدی دیده بشه و این کار لازم باشه. بنظر بنده این روش صحیح و بهینه است. یعنی برای هرچیزی باید در عمل مشکل و نیاز وجود داشته باشه که قاعدتا باید دیده بشه.
تازه بهینه سازیهای درشت رو هم اگر پیاده سازی اونها خیلی مشکل نباشه یا خوانایی کد رو خیلی کاهش ندن انجام میدم، وگرنه باید در عمل نیاز بهش اثبات بشه تا پیاده سازی کنم.

*: اینکه گفتم این پروژه برای سایتهای کوچک طراحی شده به این معنی نیست که روی یک هاست درپیت ارزان با فضای کم هم مناسب باشه (اول میخواستم بر روی ارزانترین هاستها هم کاملا قابل استفاده باشه، ولی بعد متوجه شدم یک برنامهء حرفه ای با امکانات و امنیت بالا رو نمیشه با چنین شرایطی طراحی کرد یا رسیدن به این هدف میتونه خیلی دشوار باشه که ارزش هزینش رو نداره و بهتره بجاش هاست قوی تری تهیه بشه). دیتابیس این برنامه میتونه حجم قابل توجهی داشته باشه و اگر فضای هاست خیلی کم باشه (مثلا 50 مگابایت) احتمالا با تعداد چند هزار کاربر تمام فضای آزاد هاست میتونه پر بشه، یا ممکنه هکرها از این ضعف برای حملهء خاصی سوء استفاده کرده و با پر کردن فضای هاست (مثلا با تعداد زیادی ثبت نام جدید) موجب مشکل بشن.

===================

طریقهء نصب برنامه:

- یک دیتابیس بنام reg8log رو خودتون باید شخصا ایجاد کنید.
- نام کاربری و پسورد اتصال به MySQL رو در فایل info_dbms.php وارد و سیو کنید.
- بعد وقتی صفحات برنامه رو باز کنید خودش تشخیص میده که جدولها ایجاد نشدن و لینک صفحهء نصب رو در اختیارتون قرار میده.
- وارد صفحهء نصب که شدید اول باید یک عدد رندوم رو که تولید شده از اونجا کپی کرده و در فایل setup.txt واقع در پوشهء setup درج و سیو کنید. این مرحله بخاطر اینه تا ثابت بشه شما مالک حقیقی سایت هستید و به هاست دسترسی دارید. البته این روش رو بچه ها در فروم iranphp.org مطرح کردن که ظاهرا یک برنامهء شناخته شده ای از این روش برای احراز هویت مالک سایت استفاده میکنه.
- در مرحلهء بعد باید پسورد و ایمیل اکانت ادمین رو تعیین کنید.
- اکانت ادمین برای کارهای مدیریتی این برنامه استفاده میشه. کارهایی مثل تایید یا حذف اکانت های معلق، Ban کردن و Unban کردن.
نام کاربری ادمین ثابته (Admin) و ادمین با استفاده از نام کاربریش شناسایی میشه.
- بعد از سابمیت فرم مشخصات ادمین، برنامهء نصب تمام جدولها رو با خوندن از فایلهای sql موجود در پوشهء sql (واقع در پوشهء setup) بصورت خودکار ایجاد میکنه و یکسری متغییرهای اولیهء سایت رو هم تولید و در جدول های مربوطه درج میکنه و دست آخر اکانت ادمین رو هم به دیتابیس سیستم اضافه میکنه.

===================

از ایرادهای احتمالی این برنامه میتونم به استفاده از Table برای Layout اشاره کنم.
بهرحال این اولین کار عملی بنده بعد از سالها بوده و اون زمان قدیمتر بحث استانداردهای طراحی و عدم استفاده از جدول برای Layout به اندازهء الان گسترده و جدی نبود. منم فعلا وقت نداشتم روی روشهای استاندارد امروزی در بخش پیاده سازی اینترفیس HTML بیشتر تحقیق و کار کنم، و تمام وقت و انرژی محدود خودم رو به اهداف اصلی مورد نظر این پروژه، که بحث امنیت و منطق و الگوریتم و امکانات اون بود، اختصاص دادم. ضمنا پروژه بازمتن هست و هرکس خواست میتونه تغییرش بده و اشکالاتش رو برطرف کنه. این یه پروژهء اولیه و آزمایشی است که البته سعی شده نسبت به کارهای دیگر، در کل امنیت بالاتری رو با استفاده از علم و تحلیل و طراحی تخصصی امنیت و رمزنگاری و روشهای اصولی پیشرفته و استاندارد، داشته باشه (هرچند هنوزم حداقل یکی دوتا سیستم امنیتی قابل توجه هست که در این پروژه پیاده سازی نکردم و شاید بعدا این کار انجام شد).

یک ایراد دیگری که بازم به دلایل مشابهی میتونم برای این پروژه درنظر بگیرم اینه که احتمالا متدهای استاندارد دیزاین برنامه نویسی رو درش رعایت نکردم یا بصورت کامل رعایت نکردم. مثلا نمیدونم آیا میشه اثری از متد MVC در این پروژه دید یا نه و تا چه حد. بنده شخصا با توجه به نیاز عملی، بخاطر حجم و پیچیدگی روز افزون کدهای این برنامه، از روش تقسیم و تفکیک کدها و عملیات به بخشهای مجزا و ذخیره هر قطعه کد و تابع در فایل مجزا استفاده کردم که این روش خوب جواب داد و مشکل حجم و ناخوانایی کد رو تاحد قابل تحملی کاهش داد.

احتمالا باید کدهای این برنامه رو ترکیبی از روش شیء گرا، فانکشنال، و غیره دونست چون درش هم از کلاس و اشیاء و هم از تابع و غیره استفاده شده.

===================

اگر خواستید از جدول اکانتهای کاربری این برنامه نسخهء پشتیبان تهیه کنید، باید توجه کنید که هش پسورد کاربران که در دیتابیس برنامه ذخیره شده، به اطلاعات جدول site_vars و نیز مقدار متغییر pepper در فایل کانفیگ info_crypto.php هم بستگی داره. بنابراین باید حداقل از این دو مورد هم نسخهء پشتیبان تهیه و درصورت لزوم برگردان کنید تا بعد از برگردان کردن اطلاعات، کاربران بتونن به اکانتهای خودشون لاگین کنن.

===================

این برنامه در این محیط توسعه داده و تست شده:

سیستم عامل: ویندوز XP SP3

مرورگر: FF 10 و IE 7

EasyPHP 5.3.1.0 که شامل MySQL 5.1.43 و PHP 5.3.2 و Apache 2.2.14 میشه.

این برنامه روی PHP 4 کار نمیکنه، و حتی روی نسخه های بیش از حد پایین سری 5 هم کار نمیکنه، اما فکر میکنم نسخه هایی از سری 5 که الان روی بیشتر هاستها نصب هستن برای اجرای برنامه کافی باشه.

ضمنا خواستم این پروژه رو در محیط GNU/Linux هم تست کنم، اما خودم یک نسخهء خیلی قدیمی از لینوکس رو دارم (فدورا 5) که برنامه روش درست کار نکرد. سرفرصت اگر تونستم یک نسخهء جدیدتر لینوکس رو تهیه و نصب میکنم تا بتونم سازگاری این برنامه رو در محیط لینوکس هم تست و اگر اشکالی داشت درستش کنم.

===================

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_register.php
-----------------------------------------------------------

با تنظیم متغییر ajax_check_username میشه مشخص کرد که سیستم چک کردن ایجکسی نام کاربری انتخاب شده در بخش ثبت نام فعال باشه یا غیرفعال.
این متغییر علاوه بر ایجکس فرم ثبت نام، بر روی یکسری تمهیدات امنیتی سیستم هم تاثیر غیرمستقیم میذاره (در جهت جلوگیری از افشای نامهای کاربری کاربران سیستم) و رفتار سیستم رو در این راستا تغییر میده که حالا توضیحش بماند چون از حوصلهء این مختصر خارج است.

امکان ثبت نام سیستم رو میشه با متغییر registeration_enabled فعال یا غیرفعال کرد (مثلا یک وقتی اگر خواستید کاربران بیشتری یا در زمان خاصی نتونن در سیستم ثبت نام کنن).

متغییر password_refill تعیین میکنه که در بخش ثبت نام اگر اطلاعات ثبت نام مشکلی داشت و فرم به کاربر برگردانده شد، آیا پسورد کاربر هم مجددا در فیلد پسورد بصورت خودکار پر بشه تا کاربر بعد از رفع موارد اشکال نیازی به تایپ مجدد پسورد (اونم دوبار) نداشته باشه، یا خیر.
این پسورد بصورت خودکار پر شده که از سمت سرور به کلاینت برگشت داده شده بصورت رمز شده با استفاده از الگوریتم AES128 به سمت کاربر برگردانده میشه که کلید رمزنگاری یک کلید محرمانه در سمت سرور است که موقع نصب دیتابیس بصورت خودکار و رندوم تولید میشه. بنابراین هیچکس در سمت کلاینت یا در بین مسیر نمیتونه این رشته رو رمزگشایی کنه و پسورد کاربر رو دربیاره. فقط خود سرور میتونه این رشته رو رمزگشایی و استفاده کنه.

ضمنا موقعی که کاربر برای اولین بار پسورد رو ارسال میکنه، این پسورد قبل از ارسال، در سمت کلاینت با SHA256 و به همراه یک سالت یکتا (اما غیرمحرمانه) که موقع نصب دیتابیس برنامه بصورت خودکار ایجاد شده هش میشه و بنابراین چیزی که در مسیر از PC کلاینت تا سرور منتقل میشه پسورد خام نیست بلکه یک هش است که اگر پسورد کاربر ضعیف نباشه کسی قادر نیست حتی با Sniff کردن ارتباطات، اصل پسورد کاربر رو ازش بدست بیاره (اما باید توجه داشته باشید که با سرقت چنین اطلاعاتی میتونن بجای کاربر لاگین کنن - بحث کشف اصل پسورد چیز دیگری است که اهمیت خودش رو داره).
این هش شدن پسورد قبل از ارسال، در تمام فرمهای برنامه که فیلد پسورد دارن انجام میشه (مثلا فیلدهای پسورد واقع در بخش تغییر پسورد)، و فقط منحصر به بخش ثبت نام نیست.

مقدار متغییر email_verification_needed مشخص میکنه که آیا برای قبول ثبت نام کاربران نیاز به تایید صحت ایمیل اونها با استفاده از ارسال ایمیل محتوی لینک فعال سازی هست یا خیر. اگر به این کار نیاز باشه، اکانت کاربر تا وقتی ایمیل تایید نشده معلق باقی میمونه.
کاربر باید تا زمان مشخص شده توسط متغییر email_verification_time اقدام به باز کردن لینک تایید ایمیل خودش بکنه، وگرنه اکانت معلق منقضی میشه.

متغییر admin_confirmation_needed مشخص میکنه که آیا برای نهایی شدن ثبت نام کاربران نیاز به تایید توسط ادمین هست یا خیر. برای تایید ادمین هم زمان معینی میشه تعیین کرد که با متغییر admin_confirmation_time مشخص میشه و اگر تا اون زمان ادمین اکانتی رو تایید نکنه اکانت معلق منقضی میشه.

متغییر login_upon_register مشخص میکنه که درصورت ثبت نام نهایی کاربر آیا کاربر بصورت خودکار لاگین بشه یا خیر (البته این لاگین خودکار تا مدت زمان باز بودن مرورگر وجود داره).
موقعی که نیاز به ایمیل فعال سازی یا تایید ادمین نیست و کاربر ثبت نام میکنه، بلافاصله لاگین هم میشه، چون اکانت مستقیما بعنوان یک اکانت فعال و نهایی در دیتابیس و جدول اصلی اکانتها ثبت میشه.
موقعی که نیاز به ایمیل فعال سازی است اما نیاز به تایید ادمین نیست و کاربر لینک ایمیل فعال سازی رو اجرا میکنه و اکانتش تایید نهایی میشه، بازم بصورت خودکار لاگین میشه.

متغییر max_activation_emails حداکثر تعداد ایمیل های فعال سازی رو که برای یک اکانت معلق میتونه ارسال بشه مشخص میکنه (کاربر ممکنه به هر علتی، تقاضای ارسال مجدد لینک فعال سازی رو بکنه، ولی ما برای جلوگیری از بعضی سوء استفاده ها و آزارها با استفاده از این سیستم، میتونیم تعداد ایمیل های قابل ارسال رو محدود کنیم).

متغییر can_notify_user_about_admin_action مشخص میکنه که درصورت تایید یا حذف یک اکانت معلق توسط ادمین، آیا یک ایمیل که تصمیم ادمین رو اطلاع میده به کاربر مربوطه ارسال بشه یا خیر.
البته کاربران موقع ثبت نام میتونن با برداشتن تیک یک چک باکس در فرم ثبت نام مشخص کنن که نمیخوان چنین ایمیلی براشون ارسال بشه (بخاطر همین اسم این متغییر با can_notify شروع میشه و نه با notify).

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_lockdown.php
-----------------------------------------------------------

lockdown_period مدت زمانی رو که تعداد خاصی تلاش لاگین موفق در اون بازهء زمانی اجازه داده شده مشخص میکنه.

مقدار lockdown_threshold مشخص میکنه که بعد از چند بار تلاش لاگین ناموفق، در زمان تعیین شده توسط مقدار متغییر lockdown_period، اکانت باید قفل بشه.
نکتهء مهم: مقدار این متغییر نباید از 10 بیشتر باشه، وگرنه سیستم قفل اکانت عمل نمیکنه.

مقدار captcha_threshold مشخص میکنه که بعد از چه تعدادی تلاش لاگین ناموفق برای هر اکانت خاص در مدت تعیین شده توسط lockdown_period، در دفعات بعدی برای لاگین کردن به اون اکانت نیاز به پاس کردن کپچا هم هست. این ویژگی میتونه از قفل شدن بی مورد اکانت توسط روبات های کرکر که اغلب قابلیت کرک کپچا رو ندارن، یا بعضی افراد فضول، جلوگیری کنه (این ایده رو با تست رفتار سیستم لاگین یاهو یاد گرفتم).
نکتهء مهم: مقدار این متغییر نباید از 10 بیشتر باشه، وگرنه عمل نمیکنه.

lockdown_bypass_system_enabled مشخص میکنه که اگر اکانتی قفل شد صاحب اون اکانت میتونه تقاضای ارسال یک لینک مخصوص به ایمیلش رو بکنه که با استفاده از اون لینک بتونه بدون محدودیت به اکانت قفل شده لاگین کنه، یا خیر.

max_lockdown_bypass_emails حداکثر تعداد ایمیل های قابل ارسال توسط سیستم دور زدن قفل اکانت رو مشخص میکنه.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_register_fields.php
-----------------------------------------------------------

این فایل کانفیگ حاوی الگو و محدودیت های وضع شده بر روی فیلدهای ثبت نام است. مثلا اینکه حداکثر و حداقل طول نام کاربری چی باشه و از چه کاراکترهایی تشکیل شده باشه و غیره.
راستی نام کاربری درحال حاضر میتونه فقط از حروف انگلیسی و فارسی و اعداد و فاصله های تکی در بین کاراکترها تشکیل شده باشه (شاید لازم باشه بعدا الگوی نام کاربری رو آزادتر کنیم).

ضمنا تنظیمات این متغییرها فقط در بخش ثبت نام موثر نیستن، بلکه در سراسر پروژه هرکجا که نیاز باشه استفاده میشن. مثلا فرمت پسورد که در این فایل تعیین میشه نه تنها در بخش ثبت نام اعمال میشه، بلکه در بخش تعیین پسورد جدید برای اکانت هم اعمال میشه. همینطور فرمت ایمیل در بخش تغییر ایمیل اکانت هم چک میشه.

راستی حداقل طول نام کاربری رو 1 قرار دادم (بخاطر راحتی تست) و احتمالا باید به عدد بیشتری تغییر داده بشه.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_password_change_or_reset.php
-----------------------------------------------------------

max_password_reset_emails حداکثر تعداد ایمیل های قابل ارسال سیستم ریست پسورد (ایمیل محتوی لینک لازم برای ریست کردن پسورد درصورت فراموش کردن کلمهء عبور) رو مشخص میکنه (این محدودیت تعداد در یک بازهء زمانی تعریف شده توسط password_reset_period است).

password_reset_period مدت زمانی که لینک ارسال شده در ایمیل ریست پسورد اعتبار داره رو مشخص میکنه.

change_autologin_key_upon_new_password مشخص میکنه که با ریست/تغییر پسورد آیا مقدار کلید لاگین خودکار کاربر در دیتابیس عوض بشه (و در نتیجه هکر محترم احتمالی از سیستم شوت بشه بیرون!) یا خیر. واضحه که توصیهء اکید امنیتی فعال بودن این گزینه است، چون احتمال اینکه تغییر پسورد بخاطر ترس و احتمال سرقت پسورد قبلی بوده باشه کم نیست.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_dbms.php
-----------------------------------------------------------

نام کاربری و رمز عبور دیتابیس و نام دیتابیس برنامه در این فایل تعیین میشه.
موقع نصب برنامه اول نیاز دارید تا نام کاربری و رمزعبور MySQL رو در این فایل ست کنید.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_identify.php
-----------------------------------------------------------

یکسری اطلاعات مورد استفاده برای کارکرد داخلی برنامه، مربوط به ساختارهای احراز هویت کاربران، در این فایل قرار دارن.

از جمله متغییرهایی در این فایل که کاربران عادی ممکنه نیاز به تغییر اونها داشته باشن:

متغییر long_age که طول عمر کوکی لاگین خودکار رو در حالت لاگین بادوام مشخص میکنه. مثلا اگر میخواید کاربر بتونه حداکثر به مدت 6 ماه نیاز به لاگین دستی نداشته باشه میتونید مقدار این متغییر رو (بر حسب ثانیه) 6 ماه تعیین کنید.

متغییر change_autologin_key_upon_login میتونه سه مقدار بگیره.

حالت اول (0) اینه که درصورت لاگین دستی یا بازدید مجدد یک کاربری که از قبل لاگین هست، کلید لاگین اون کاربر در دیتابیس عوض نمیشه.

حالت دوم (1) اینه که درصورت لاگین دستی، کلید لاگین کاربر در دیتابیس عوض میشه، و بنابراین سیستمهای دیگری که کاربر از قبل روی اونا لاگین بوده از لاگین خارج میشن (ولی نه سیستمی که کاربر الان توش لاگین کرده). این گزینه میتونه باعث افزایش امنیت بشه. هم از نظر احتمال فراموش کردن لاگ آوت روی سیستمهایی که کاربر در جاهای دیگری قبلا استفاده کرده بوده و هم از نظر محدود کردن زمان دسترسی هکری که به هر نحوی تونسته کوکی/کلید لاگین کاربر رو بدست بیاره.
طبیعتا با این کانفیگ، کاربر نمیتونه همزمان روی دو سیستم لاگین بمونه.

حالت سوم (2) اینه که نه تنها در هر بار لاگین دستی، بلکه در هر بار بازدید مجدد، یعنی هر درخواست و Page view توسط کاربر، کلید لاگین عوض میشه. این بالاترین امنیت رو میده و برای جاها و مواردی که به امنیت حداکثری نیاز دارن توصیه میشه، ولی در عین حال بخاطر اینکه در این حالت هر Page view هر کاربر موجب یک عملیات Write در دیتابیس میشه، این گزینه رو بصورت پیشفرض فعال نکردم.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_crypto.php
-----------------------------------------------------------

secure_hash_rounds تعداد دورهای هش امنیتی رو مشخص میکنه. یعنی تعداد دورهایی که برای Key stretching موقع تبدیل پسورد کاربر به هش برای ذخیره در دیتابیس، عملیات هش تکرار میشه. مقدار پیشفرض 16 است. توجه کنید که تعداد دورهای واقعی هش از 2 به توان این عدد حاصل میشه (یعنی 2 به توان 16 و غیره).

مقدار متغییر pepper یک رشتهء رندوم 22 کاراکتری متشکل از اعداد و حروف بزرگ و کوچک انگلیسی است که موقع نصب برنامه، و حتما قبل از اجرای بخش نصب دیتابیس برنامه، میتونید بصورت دستی Set کنید تا به این شکل امنیت بازهم بالاتر بره.
این رشته در بخشهای مختلفی از سیستم استفاده میشه و مزیت چندجانبه داره، ولی در اصل در ابتدا فقط بعنوان سالت ثابت موجود در فایل (و نه دیتابیس) برای شرکت در فرایند تولید هش از پسورد کاربران درنظر گرفته شده بود. الان این متغییر مثلا در جریان تولید اعداد رندوم امن هم بعنوان یک منبع آنتروپی اولیه استفاده میشه، و در رمزگذاری هم بعنوان بخشی از کلید ترکیبی استفاده میشه.
البته بنده سیستم رو طوری طراحی کردم که حتی اگر مقدار این متغییر از مقدار پیشفرض تغییر داده نشه، امنیت بازهم بالا باشه، یعنی برای برقراری امنیت به انجام این کار توسط کاربر اتکا نکردم، اما با انجام این کار امنیت طبیعتا بالاتر میره.

مقدار متغییر encrypt_session_files_contents مشخص میکنه که آیا محتویات فایلهای سشن برنامه که در سمت سرور ذخیره میشن رمز بشن یا خیر.
این سیستم رمزگذاری طوری طراحی شده که اگر فعال باشه باعث میشه: 1- کسی قادر به خواندن اطلاعات داخل فایلهای سشن کاربران نیست 2- کسی نمیتونه حتی بصورت کورکورانه این اطلاعات رو دستکاری کنه (اگر دستکاری صورت بگیره، بخاطر وجود HMAC حتما Detect شده و اطلاعات داخل فایل سشن کلا دور انداخته میشه) 3- یک ویژگی جالبی که توسط این سیستم که ابتدا چنین کاربردی رو هدف نداشت ایجاد شد، اینه که حتی اگر هکر Session id کاربران رو از طریق سمت سرور سرقت کنه، قادر نخواهد بود خودش رو بجای اونا جا بزنه، چون اطلاعات داخل فایلهای سشن نه تنها با یک کلید محرمانه ثابت برای کل سایت که موقع نصب برنامه بصورت خودکار تولید شده رمز میشن (با الگوریتم AES128)، بلکه یک کلید رندوم که به ازای هر جلسه تولید میشه و در قالب یک کوکی در کلاینت تا مدت باز بودن مرورگر ذخیره شده هم در تولید کلید ترکیبی مورد استفاده در این رمزگذاری نقش داره. در نتیجه فقط داشتن Session id برای استفاده از سشن دیگران کافی نیست.
البته باید توجه داشت که اگر نفوذگر دسترسی نوشتنی به فایلهای سشن ما داشته باشه بنابراین میتونه یک حملهء DOS رو اجرا کنه (خارج کردن سایت از حالت سرویس دهی به کاربران با تخریب مداوم فایلهای سشن)؛ این سیستم فقط جلوی سرقت اطلاعات و جعل هویت رو میگیره.
بهرحال گذشته از اینها شما میتونید با تعیین مقدار متغییر save_path در فایل info_identify.php دایرکتوری محل ذخیرهء سشن های برنامه رو تعیین و از بقیهء برنامه ها و سایتهای روی سرور جدا کنید تا احتمال دسترسی غیرمجاز به سشن های شما خیلی کمتر بشه.

نکته: البته موقع نصب اولیهء برنامه چون هنوز دیتابیس نصب نشده و کلیدهای سایت ایجاد نشدن، محتویات سشن رمزگذاری نمیشه.

ضمنا برنامهء ما درحال حاضر از سشن استفادهء امنیتی مهمی نمیکنه (لاگین خودکار فقط با استفاده از کوکی و دیتابیس انجام میشه) که بخوایم نگران سرقت سشن کاربران باشیم، اما بهرحال این یک مقدار امنیت بیشتر و لایهء اضافه و اطمینان برای آینده و امکان ذخیرهء اطلاعات مهمتری در سشن هست و کلا سیستمی که میتونه در موارد دیگری هم بدرد بخوره.

مقدار store_request_entropy_probability که عددی بین 0 و 1 است (البته نباید خود صفر باشه) مشخص میکنه که با چه احتمالی آنتروپی موجود در درخواستهای کاربران در دیتابیس ذخیره بشه. این آنتروپی برای اطمینان بیشتر از تولید اعداد رندوم امن و غیرقابل پیشبینی استفاده میشه. تولید اعداد رندوم امن در این برنامه و بطور کلی در وب واقعا مهمه، و توابعی مثل mt_rand و اکثر روشهای دیگری که برنامه نویسان خودشون برای این منظور ابداع میکنن از نظر اصول علم رمزنگاری امنیت کافی ندارن (در بعضی موارد نتیجه میتونه پایین بودن شدید امنیت باشه).
ضمنا این برنامه علاوه بر استفاده از آنتروپی درخواستها، از یک تابع تولید اعداد رندوم خیلی قویتر از توابع و روشهای عادی استفاده میکنه که این تابع درصورت در دسترس بودن منابع تولید اعداد رندوم امن تر در سیستم (مثل /dev/urandom)، از اونها استفاده میکنه.
مقدار پیشفرض این متغییر 1 است که یعنی آنتروپی تمام درخواستها همیشه ذخیره بشه، ولی اگر کاهش کارایی بخاطر بار زیاد عملیات دیتابیس مشاهده شد، میشه مقدارش رو کم کرد و مثلا روی 0.5 یا کمتر گذاشت که بطور مثال این مقدار 0.5 یعنی شانس ذخیرهء آنتروپی در هر درخواست 50% است.
البته متغییر دیگری بنام store_request_entropy_probability2 که در ابتدای بعضی صفحات اصلی تعریف شده، مقدار این متغییر رو Override میکنه، و این بخاطر ارزش بالای آنتروپی بعضی صفحات مثل صفحهء ثبت نام است که میخوایم حتما از این آنتروپی حداکثر استفادهء مفید بشه.
ضمنا حتی اگر آنتروپی یک درخواست ذخیره نشه، ولی در تولید اعداد رندوم همون درخواست شرکت میکنه و بنابراین امنیت کاربران رو بالاتر میبره (ولی امنیت خود برنامه در برابر کاربران/هکرها مسئلهء جداگانه ایست).

-----------------------------------------------------------
متغییرهای پیکربندی در فایل کانفیگ info_cleanup.php
-----------------------------------------------------------

cleanup_probability عددی بزرگتر از صفر و کوچکتر یا مساوی یک است که مشخص میکند با چه احتمالی سیستم پاکسازی دیتابیس بخشهای مختلف برنامه، در هر عملیات درج اجرا میشه. بطور مثال اگر مقدار این متغییر 0.1 باشه، بطور متوسط در هر ده بار که اکانتهای معلق در دیتابیس ذخیره میشن کوئری های پاکسازی هم اجرا میشن تا رکوردهایی رو که تاریخ انقضای اونها گذشته از دیتابیس حذف کنن. همینطور برای اجرای فرایند پاکسازی بقیهء رکوردهای موقتی در جداول دیگری مثل جدول ریست پسورد و غیره، از این متغییر استفاده میشه.

max_nonexistent_users_records مشخص میکنه که حداکثر تا چه تعداد رکورد برای اسامی کاربری ای که واقعا در سیستم وجود ندارن در دیتابیس قابل درج است.
در این مورد باید توضیح بدم که، اگر بخش ثبت نام سیستم رو غیرفعال کرده باشیم یا چک کردن ایجکسی نام کاربری در فرم ثبت نام غیرفعال باشه، وقتی کسی اقدام به لاگین با یک نام کاربری ناموجود در سیستم میکنه، سیستم با اون نام کاربری مثل نامهای کاربری که واقعا در سیستم ثبت شدن رفتار میکنه تا هکر نتونه از رفتار و پیامهای سیستم (مثل قفل شدن یا نشدن یک اکانت بعد از تعدادی تلاش برای لاگین) متوجه بشه که آیا یک نام کاربری خاص در بین کاربران واقعی سیستم وجود دارد یا خیر.
برای این وانمود کردن، سیستم نیاز داره که بطور مثال اطلاعات مربوط به درخواستهای لاگین ناموفق با نامهای کاربری ناموجود در سیستم رو هم بصورت موقتی در دیتابیس ذخیره کنه، اما اگر تعداد چنین رکوردهایی رو در دیتابیس محدود نکنیم، میتونه موجب حجیم شدن بیش از حد دیتابیس بر اثر حمله هایی که برای سوء استفاده از این ضعف صورت میگیرن بشه و فضای آزاد هاست رو هم تاحداکثر پر کنه. بنابراین ما میتونیم حداکثر تعداد رکوردهای مربوط به نامهای کاربری ناموجود رو با این متغییر تعیین کنیم تا اگر تعداد این رکوردها از این تعداد بیشتر شد، یک تعدادی از قدیمی ترین چنین رکوردهایی موقع اجرای پاکسازی دیتابیس حذف بشن تا فضای متوسط اشغال شده توسط این رکوردها از مقدار مشخصی تجاوز نکنه. توجه کنید که ممکنه مقدار پیشفرض این متغییر بیش از فضای مجاز هاست شما باشه و در این صورت باید تغییرش بدید. البته تا وقتی امکان چک کردن نامهای کاربری با استفاده از ایجکس فرم ثبت نام وجود داره، این سیستم عمل نمیکنه، چون وقتی هرکس میتونه وجود یک نام کاربری در سیستم رو با استفاده از ایجکس فرم ثبت نام براحتی چک کنه نیازی به این کارها نیست.

-----------------------------------------------------------
متغییرهای پیکربندی در فایل common.php
-----------------------------------------------------------

این فایل فقط یک فایل کانفیگ نیست و در ابتدای هر صفحهء اصلی برنامه اینکلود میشه، اما دوتا متغییر کانفیگ هم درش هست:

مقدار true برای متغییر کانفیگ debug_mode برای تست و باگیابی برنامه بکار میره و در این حالت مثلا تمام پیامهای هشدار و خطا نمایش داده میشن؛ همچنین موقعی که ایمیل فعال سازی یا ریست پسورد و غیره ارسال میشن، اگر این متغییر true باشه لینک مورد نظر در صفحه echo میشه تا بدون نیاز به داشتن سرور ارسال ایمیل و چک کردن ایمیل بتونید لینک ارسالی رو ببینید و بقیهء مراحل رو با استفاده از کپی و پیست کردن اون در نوار آدرس مرورگر تست کنید. بنابراین برای کاربرد واقعی و عمومی، مقدار این متغییر حتما باید false باشه.
این متغییر درحال حاضر بصورت پیشفرض روشنه تا دیگران بتونن برنامه رو تست کنن و پیام خطا و باگ هایی که در برنامه هستند کشف بشن.

با تعیین متغییر db_installed به مقدار true میتونید برای برنامه مشخص کنید که جدول ها و اطلاعات دیتابیس قبلا نصب شدن. به این شکل دیگه برنامه خودش با اجرای یک کوئری آزمایشی اقدام به تشخیص نصب بودن دیتابیس نمیکنه. این متغییر رو فقط برای افزایش پرفورمنس برنامه (درصورت لزوم) قرار دادم، وگرنه بدون ست کردن این متغییر هم برنامه به خوبی کار میکنه.

eshpilen
سه شنبه 22 فروردین 1391, 17:55 عصر
کسانی که میخوان برنامه رو نصب کنن توجه کنن که فایل setup.txt در پوشهء setup برنامه است، نه در ریشه.
چون یک نفر فکر کرده بود این فایل رو باید در ریشه ایجاد کنه و به مشکل خورده بود گفتم روی این نکته تاکید کنم.
راستی من این برنامه رو فقط روی لوکال ویندوز تست کردم. اگر کسی روی هاست واقعی تست کرد نتیجه رو اطلاع بده.

eshpilen
چهارشنبه 23 فروردین 1391, 19:33 عصر
یه باگ امنیتی توی سیستم بنظرم رسید.

اگر یک هکر در سایت عضو بشه بعد میتونه بوسیلهء گزینهء تغییر ایمیل، وجود ایمیل های مختلف در سایت رو بدون محدودیت چک کنه. یعنی چون نیاز به پاس کردن کپچا برای تغییر ایمیل نذاشتم، میتونه این کار رو به یک برنامهء خودکار بسپاره.

ما باید حتی الامکان از هرگونه Information leakage در سیستم جلوگیری کنیم (یا اگر نمیشه کامل جلوگیری کرد، حداقل اون رو تا حداکثر ممکن محدود/دشوار کنیم) تا امنیت سیستم به حداکثر برسه و در محیطهای نیازمند security بالا هم قابل استفاده باشه. بخصوص باید امکان استفاده از روبات ها رو در بخشهای مختلف بگیریم.

افشا نشدن ایمیل هم از نظر Privacy و هم از نظر امنیت اهمیت داره.

خب میتونم برای این قضیه براحتی یک کپچا بذارم. اما مایل نیستم همه جا کپچا بارون بشه و این رو حرفه ای نمیدونم که برای راحت کردن خودمون بیایم و زرت و زرت همه جا برای همه کاری کپچا بذاریم. هرچند شاید کپچا از دید بعضی افراد قشنگی و کلاس داشته باشه یا برای اینکه وانمود کنیم سیستم حرفه ای و امنه اون رو به رخ بکشیم، اما بنظر بنده در واقعیت از نظر اصول و یوزرفرندلی بهتره استفاده از اون به حداقل ممکن برسونیم.

واسه همین فکر کردم timestamp مربوط به آخرین بار درخواست تغییر ایمیل رو در یک ستون اضافه در جدول اکانتها ذخیره کنم. بعد میتونم براحتی چک کنم مثلا اگر فاصلهء آخرین درخواست تغییر ایمیل با درخواست فعلی کمتر از فرضا یک هفته بود، کاربر رو وادار به پاس کردن کپچا کنم. به این شکل دیگه برای تغییر ایمیل های طبیعی که پیش میاد، کاربران مجبور به مواجه شدن با کپچا نیستن، و از طرف دیگر اگرچه یک روبات هنوز میتونه درخواست رو به این سیستم سابمیت کنه، اما فقط میتونه در هر هفته یک بار این کار رو انجام بده، که فکر میکنم برای کاربرد ما کاملا کافی باشه و عملا روبات رو بی فایده میکنه، چون کاربر خودش میتونه این کار رو با سرعت خیلی بیشتری از روبات انجام بده (نیازی نیست یک هفته برای چک کردن هر ایمیل منتظر بمونه!!).

بنظرتون ایدهء خوبیه؟

eshpilen
جمعه 25 فروردین 1391, 15:55 عصر
نسخهء جدید 0.6 رو ضمیمهء پست اول کردم.

تغییرات این نسخه شامل:

- رفع چند باگ امنیتی (که از این بابت دو فیلد به جدول accounts اضافه شد + مقداری مکانیزم و چند فایل کد جدید).
این باگها یکیش امکان جستجوی Brute-force پسورد کاربر با استفاده از بخش تغییر پسورد بود که البته این سوء استفاده فقط وقتی پیش میاد که کوکی/کلید لاگین کاربر سرقت شده باشه یا سیستمی که کاربر روش لاگین بوده و خارج نشده، زیر دست افراد دیگر بیفته که بعد بتونن از طریق بخش تغییر پسورد، پسوردهای مختلف رو چک کنن تا به پسورد اصلی کاربر پی ببرن.
البته نمیشه کاملا جلوی این قضیه رو گرفت، مگر اینکه درصورت وارد شدن تعدادی پسورد اشتباه، اکانت رو قفل کنیم * (که شاید در نسخه های بعدی پیاده کردم). فعلا بنده فقط یک کپچا اضافه کردم که جلوی انجام این حمله با استفاده از روبات رو میگیره.
باگ دیگر که قبلا بهش اشاره کرده بودم، امکان جستجوی Brute-force برای ایمیل های موجود در دیتابیس بود به این شکل که هکر در سایت ثبت نام میکنه و سپس از طریق بخش تغییر ایمیل میتونه موجود بودن ایمیل های مختلف در دیتابیس رو چک کنه. در این مورد هم یک کپچا اضافه کردم تا امکان انجام این کار توسط روبات وجود نداشته باشه.

- رفع چند باگ تقریبا غیرامنیتی (کاربری) در بعضی بخشها، بخصوص رفع باگ پر شدن خودکار فیلدهای پسورد در بعضی صفحات وقتی که جاوااسکریپت و در نتیجه ولیدیت سمت کلاینت غیرفعال بود و پسورد در سمت سرور هم با موفقیت ولیدیت نشده بود، و بنابراین این کار نباید انجام میشد.

- کمی سازماندهی و تمیزکاری کد در بعضی بخشها (بخصوص متمرکز کردن کدهای ولیدیت کردن کپچا که در صفحات مختلف تکرار شده بود در یک فایل کد مخصوص خودش که الان توسط تمام صفحاتی که ولیدیت کچای سمت سرور نیاز دارن include میشه).

- افزودن مقداری یوزرفرندلی بیشتر (مثلا افزودن امکان پر شدن مجدد/خودکار فیلد پسورد جدید در بخش تغییر پسورد).

- بردن منوی گزینه ها به سمت چپ (چون زبان انگلیسی است).

- برطرف کردن باگ عدم ولیدیت پسورد ادمین در سمت سرور در صفحهء نصب دیتابیس موقعی که جاوااسکریپت کلاینت خاموش بود. این باگ بخاطر ترتیب جابجای دو خط از کد بوجود آمده بود.

--------------------------------

*: یه راه دیگه که بعدا بنظرم رسید، تغییر کلید لاگین هست که از نظر یوزرفرندلی بهتره (چون اکانت بی جهت قفل نمیشه) و عملا باعث لاگ آوت شدن طرف میشه.

eshpilen
جمعه 01 اردیبهشت 1391, 19:02 عصر
نسخهء 0.7 پروژهء سیستم رجیستر و لاگین ضمیمه پست اول شد.

از جمله تغییرات و چیزهای جدید این نسخه:

- کمی بهینه سازی یا احتمالا رفع یک باگ نسبتا جزیی در عملیات cleanup جدول هایی که محدودیت تعداد رکورد روی اونها وضع شده.

- مقداری تمیزکاری های جزیی و اصلاح اینترفیس و پیامها.

- اضافه کردن سیستم جلوگیری از Brute-force پسورد با استفاده از فرم تغییر ایمیل و فرم تغییر پسورد.

- اضافه کردن سیستم ضد Brute-force لاگین بر اساس IP.
سیستم بر اساس اکانت رو که از قبل داشتیم، اما بر اساس IP رو خیر. سیستم محدودیت بر اساس اکانت از حمله به یک اکانت خاص میتونه جلوگیری کنه، اما جلوی حمله بر اساس چک کردن تعداد زیادی نام کاربری متفاوت و پسورد متفاوت رو بطور بقدر کافی موثری نمیگیره.

===================================
توضیح متغییرهای کانفیگ جدید در فایل info_lockdown.php:
===================================

ip_captcha_threshold مشخص میکنه که بعد از چند بار لاگین ناموفق از طریق یک IP، برای تلاشهای لاگین بعدی از جانب آن IP نیاز به پاس کردن کپچا باشه.

ip_lockdown_threshold مشخص میکنه که بعد از چند بار لاگین ناموفق از یک IP، جلوی تلاشهای لاگین بعدی از طرف اون IP گرفته بشه (البته این وضعیت بعد از سپری شدن زمانی به میزان حداکثر ip_lockdown_period برطرف میشه).

ip_lockdown_period مدتی رو که محدودیت تلاشهای لاگین بر اساس IP در اون بازهء زمانی محاسبه میشن. یعنی مثلا اگر مقدار این متغییر برابر 1 ساعت باشه و ip_lockdown_threshold برابر 14، از طریق هر IP در هر ساعت میشه حداکثر 14 تلاش لاگین ناموفق داشت.

ip_lockdown_proportional مشخص میکنه که آیا نسبت تعداد لاگین های ناموفق به موفق، برای اعمال محدودیت ملاک قرار داده میشه یا تعداد لاگین های ناموفق به تنهایی.
بخاطر این نسبت تعداد لاگین های ناموفق به موفق رو حساب میکنیم و نه تعداد لاگین های ناموفق به تنهایی رو، چون یک IP ممکنه بین تعداد کم یا زیادی کاربر به اشتراک گذاشته شده باشه و بنابراین تعداد لاگین های ناموفق اون IP مربوط به فقط یک کاربر نیست و میتونه حاصل خطای انسانی ده ها و صدها کاربر باشه که در این صورت نباید اون IP بخاطر بالا بودن تعداد تلاشهای لاگین ناموفق بلاک بشه. ضمنا به دلیل مسائل امنیتی، هر تعداد لاگین موفق به هر اکانت خاص، در بازهء زمانی ip_lockdown_period، فقط یک بار شمرده میشه (اما تمام لاگین های ناموفق شمرده میشن).
بهرصورت اگر این سیستم نسبتی مشکلی ایجاد کرد یا بنظر کسی از نظر امنیتی مشکل داشت، میشه با تعیین مقدار این متغییر به false اون رو غیرفعال کرد.

--------------------------

ch_pswd_captcha_threshold مشخص میکنه که بعد از چه تعدادی وارد شدن پسورد فعلی نادرست در فرم تغییر ایمیل یا تغییر پسورد، برای دفعات بعدی نیاز به پاس کردن کپچا باشه.
ما روی تعداد پسوردهای نادرست در بخش تغییر ایمیل و پسورد محدودیت میذاریم تا اگر کوکی/کلید لاگین کاربری به سرقت رفت یا بخاطر فراموش کردن لاگین در جایی، اکانتش زیر دست دیگران افتاد، نتونن با استفاده از این فرمها اقدام به حدس و تست یا Brute-force جهت بدست آوردن اصل پسورد کاربر بکنن.

بعد از تعداد ch_pswd_max_threshold بار وارد شدن پسورد اشتباه در بخش تغییر ایمیل یا پسورد، کلید لاگین اکانت مورد نظر تغییر کرده و در نتیجه کاربر فعلی که پسوردهای اشتباه رو وارد کرده بوده اجبارا از سیستم خارج میشه.

تعداد پسوردهای اشتباه ممکن در بازهء زمانی ch_pswd_period محاسبه میشه.
فرضا اگر این متغییر برابر 12 ساعت باشه و ch_pswd_max_threshold برابر 6 باشه، در هر 12 ساعت میشه حداکثر 6 پسورد اشتباه در بخش تغییر ایمیل یا پسورد وارد کرد و اگر از این تعداد تجاوز بشه، کلید لاگین عوض شده و در نتیجه کاربر اجبارا Logout میشه.

البته باید توجه داشت که تغییر کلید لاگین باعث از لاگین خارج شدن تمام سیستمها میشه؛ منجمله سیستمی که مالک واقعی اکانت درحال حاضر روی اون لاگین است. ولی بهرحال این وضعیت خیلی بهتر از قفل شدن اکانته.

===================================
توضیح متغییرهای کانفیگ جدید در فایل info_cleanup.php:
===================================

max_login_attempt_records حداکثر تعداد رکوردهایی رو که برای لاگین های موفق و ناموفق در جدول correct_logins یا incorrect_logins درج میشن مشخص میکنه. این متغییر رو برای جلوگیری از حجیم شدن بیش از حد این جدولها درنظر گرفتم که بخصوص بصورت عمدی یا موقع حملات DDOS این وضعیت بوجود نیاد.
مقدار پیشفرض رو روی یک میلیون رکورد گذاشتم (اگر تعداد رکوردها در هر دو جدول رو درنظر بگیریم مقدار حداکثر ممکن میشه دوبرابر این مقدار) تا در بدترین حالات ممکن، حداکثر حجم جدول ها از حدود 20 30 مگابایت بیشتر نشه، اما اگر مشکل حجم ندارید میتونید مقدارش رو بیشتر کنید.
ضمنا سعی کردم حجم هر رکورد این دو جدول رو به حداقل برسونم تا تعداد بیشتری رکورد رو بشه ذخیره کرد. هرچی تعداد رکوردهای قابل ذخیره بیشتر باشه از نظر امنیتی بهتره چون میشه جلوی حملات بزرگ تری رو بصورت بهینه تری گرفت.
البته اینکه بشه جلوی حملات تا چه حدی بزرگ رو گرفت بستگی به قدرت سرور و تعداد درخواستهای قابل پردازش در واحد زمان، و نیز مقدار متغییر ip_lockdown_period هم داره. هرچی مقدار ip_lockdown_period بیشتر باشه حمله فرصت بیشتری برای ارسال و انجام درخواستهای بیشتری خواهد داشت و بنابراین تعداد رکوردها میتونه راحتتر به حداکثر ممکن رسونده بشه که در این حالت تعدادی از رکوردهای قدیمی تر حذف میشن که در نتیجه سابقهء لاگین از اون IP ها از بین میره و بنابراین امنیت تامین شده توسط این سیستم کمتر میشه.
البته مقدار متغییرهای دیگر مثل ip_lockdown_threshold یا ip_captcha_threshold هم موثره. مثلا هرچی مقدار این متغییر بیشتر باشه، حمله کننده با هر IP که در اختیار داره میتونه تعداد بیشتری نام کاربری و پسورد رو تست کنه و تعداد بیشتری هم رکورد در دیتابیس به ازای هر IP درج میشه. ولی اگر این تعداد بیش از حد کم باشه یا بازهء زمانی بیش از حد بزرگ باشه، ممکنه از نظرهای دیگه و برای کاربران مشکل و آزار ایجاد کنه. خلاصه این تنظیمات همه به هم وابسته هستن و ظرافت زیادی دارن؛ بنده سعی کردم مقدارهای پیشفرض متعادل و بهینه ای رو براشون انتخاب کنم.
با اینکه توان این سیستم محدودیت داره اما وجودش از نبودنش خیلی بهتره و ضمنا احتمال و دشواری وقوع چنان شرایط وخیمی در عمل شاید به حدی باشه که برای بیشتر سایتها مشکل جدی ای محسوب نشه. یک نفر که بخواد حمله های وسیعی رو صورت بده و از ضعف محدودیت تعداد رکوردهای ما سوء استفاده کنه، بعلاوهء امکان سرعت بالای ارسال درخواستها (بیش از صدها درخواست در ثانیه)، نیاز به در اختیار داشتن تعداد زیادی IP داره (مثلا بیش از صد هزار IP) که بنظرم چنین چیزی نیاز به در اختیار داشتن یک Botnet داره. بهرصورت اگر هاست شما قدرت و فضای کافی داشت میتونید مقدار max_login_attempt_records رو زیاد کنید تا بتونید جلوی حمله های بزرگتری رو بگیرید.
ضمنا توجه داشته باشید که این سیستم اعمال محدودیت بر لاگین ناموفق و بر اساس IP، برای جلوگیری از حملات DDOS طراحی نشده و جلوی DDOS رو نمیگیره، بلکه صرفا برای جلوگیری از Brute-force در بخش لاگین سایت طراحی شده که امنیت اکانتهای کاربران رو تامین کنه. DDOS حمله ای است که برای از سرویس خارج کردن سایت صورت میگیره، نه برای کشف پسورد و نفوذ به اکانتهای کاربران.

eshpilen
یک شنبه 03 اردیبهشت 1391, 00:36 صبح
نسخهء 0.7.1 منتشر شد.
تغییرات: رفع یک مورد باگ SQL Injection.
این لامصب از زیر دستم در رفته بود :لبخند:
توی کدهایی بود که در آخرین نسخه ها اضافه کرده بودم.

wallfa
یک شنبه 03 اردیبهشت 1391, 09:43 صبح
این ریکوئری هایی که میکنی برات مشکل ساز نمیشه ؟ به همین حالت ساده ؟



require 'include/info/info_register_fields.php';

نمونه انجام شده

require_once( dirname(__FILE__) . '/config.php' );

wallfa
یک شنبه 03 اردیبهشت 1391, 09:46 صبح
قسمتی هم برای سطح دسترسی کاربران در نظر گرفتی ؟
نظر من اینه بهتر از این هم می شد نوشته بشه ! تو باید کلاس ایجاد می کردی و یه جورایی فقط توی این صفحات که ایجاد شده توابع یا اشیائ کلاس معرفی می کردی !
الان یه نفر قصد استفاده از این داشته باشه چی کار باید بکنه ؟

wallfa
یک شنبه 03 اردیبهشت 1391, 09:53 صبح
این نمونه بررسی کن میتونه برات یه ایده خوب باشه ! :متفکر:

eshpilen
دوشنبه 04 اردیبهشت 1391, 15:40 عصر
این ریکوئری هایی که میکنی برات مشکل ساز نمیشه ؟ به همین حالت ساده ؟

مشکل خاصی بنظرم نمیرسه. تاحالا منبع و مثالی ندیدم که اینطور اینکلودهای ساده و مستقیم مشکلی داشته باشن.
شاید منظور شما حملات RFI و/یا LFI باشه که تاجاییکه میدونم این حمله ها تنها در اینکلودهایی میتونن ممکن باشن که دیتای غیرقابل اعتماد (عمدتا ورودهای کاربر و پارامترهایی که از سمت کلاینت ارسال شدن) در آدرس اونها بکار میره. ولی من در این اینکلودها جز رشته های ثابت خود برنامه چیزی ندارم. بنظر شما چطور ممکنه چه خطری رخ بده؟ دقیقا سناریو و مثالی بیار یا دلیل و منبع و سند روشنی چیزی خلاصه.


قسمتی هم برای سطح دسترسی کاربران در نظر گرفتی ؟
سطح دسترسی هم میشه براش اضافه کرد. کار مشکلی بنظر نمیرسه. یک سطح دسترسی حداقلی موقع ثبت نام برای همه تعیین بشه و بعدا ادمین سطح دسترسی هر کاربری رو که خواست میتونه تغییر بده. درسته؟

بنده فکر نکردم سطح دسترسی جزو امکانات اصلی و باید ها باشه، چون در خیلی کاربردها سطح دسترسی خاصی نداریم جز ادمین و کاربران عادی و نیازی به سیستم سطح دسترسی جداگانه نیست.
در ضمن بنظرم سطح دسترسی رو میشه به چند شکل پیاده سازی کرد که بستگی به کاربرد و شرایط و بقیهء سایت و ساختار و امکانات و برنامه های اون داره که چه شکل و ساختاری داشته باشه، بنابراین فکر میکنم پیاده سازی یک شکل خاص از سطح دسترسی درحال حاضر کار چندان عاقلانه ای نباشه و ممکنه بیشتر اتلاف وقت و انرژی بشه تا کار مفید. اگر بخوایم این کار رو بکنیم باید اول روی این تحقیق کنیم که یک سیستم سطح دسترسی معین که بدرد همه جا و همهء کاربردها بخوره واقعا میتونه ایجاد بشه و به چه شکلی.


الان یه نفر قصد استفاده از این داشته باشه چی کار باید بکنه ؟ این پروژه شخصی بنده بوده برای تمرین و محک برای خودم و همچنین امکان نیازهای آیندهء خودم. تا یک حدی که فکر میکردم فعلا معقول هست پیش برم اون رو طراحی و پیاده سازی کردم. بقیش به نیاز و تجربه و تحلیل های احتمالی در آینده برمیگرده که به چه شکلی تغییر و گسترش پیدا بکنه یا نه. الان نمیتونم خیلی بیشتر از این روش کار کنم، چون اطلاعات و نیاز و تجربه و ایدهء مطمئنی درباره بقیهء ماجرا ندارم. تا اون حدی که اطلاعات و بینش خوبی درباره امکانات مورد نیاز و بخصوص مسائل امنیتی داشتم روش کار کردم بعنوان یک هسته. فعلا در این حد درست کردم که بخش پایه ای و دشوار و حجیم مهمی رو انجام داده باشم و اگر در آینده نیاز پیدا کردم (میدونید که سیستم رجیستر و لاگین تقریبا هرجایی نیازه) دیگه معطل نشم و کار خیلی دشوار و ترسناکی رو پیش رو نداشته باشم.
ولی چون هم طرفدار نرم افزار آزاد/بازمتن هستم و به این فلسفه و اجتماع واقعا مدیون هم هستم و ازش خیلی بهره بردم تا به اینجا رسیدم، و از طرف دیگه بخاطر استفاده از کمک های کاربران در فرومهای مختلف در جریان این پروژه و نیز بطور کلی موارد بحث و همفکری و کمک دیگر در گذشته، و با توجه به تحملی که بخرج دادن، وظیفه دیدم که این نرم افزار رو بصورت بازمتن منتشر کنم و انحصارگر بازی درنیارم!!
حالا بقیش دیگه با هرکس هست که میخواد و میتونه از این نرم افزار استفاده کنه. بنده وظیفه و قول و تعهد خاص بیشتری در این زمینه ندادم و نمیبینم و وقت و انرژی نامحدود هم ندارم. میتونم روی پروژه های جالب دیگری هم کار کنم که بنظرم هم برای خودم و هم احتمالا برای دیگران میتونن مفید باشن. بقول معروف هم میگن دندان اسب پیشکشی رو که نمیشمارن. بازمتن یعنی همین که کدمنبع و اختیارات لازم رو داری و اگر نقص یا مشکلی هست و میخوای و توانش رو داری باید خودت آستین بالا بزنی. خیلی از پروژه های بازمتن حتی بصورت خیلی اولیه و یا ناقص منتشر شدن. البته بنده سعی کردم این برنامه از نظر امکانات مهم پایه ای و امنیت درحد واقعا خوبی باشه. بخصوص چون در بحث امنیت خیلی مطالعه و بنظرم دانش و بینش خوبی داشتم خواستم یک کار مفیدی در این زمینه بکنم و با توجه به اینکه تاحالا هیچ نشانه ای از یک کار کامل و قوی در این زمینه ندیدم، یک مورد از چنین چیزی رو بسازم و نشون بدم و راه رو باز کنم. حالا ممکنه این برنامه در این زمینه هنوز باگ و کم و کسری داشته باشه، چون اولین کار عملی گستردهء بنده و چیزی هست که هنوز در عمل هم بقدر کافی استفاده و آزمون و بررسی و تحلیل حرفه ای نشده، اما میتونم بگم با این حال اگر یک مورد پیدا کردید که از نظر امنیتی حتی به یک دهم کمال و قدرت این پروژه میرسید بنده واقعا متعجب خواهم شد. خلاصه امنیتش و اینا واقعا علمی و حرفه ای و پیشرفته و کامل کار شده درحدی که بنده چند سال روی مسائل امنیتی و رمزنگاری مطالعه داشتم و تاجاییکه دیدم عموما دانش و بینش و کارهای دیگران در این زمینه واقعا ضعیف بودن.
چند مورد از سیستمهای امنیتی مهمی که در این پروژه استفاده شدن واقعا پیشرفته و اگر اختراع نباشن حداقل کمیاب و ابتکارهای بسیار جالب و پیشرفته ای هستند.
اصولا هدف اول هم یک کار با امنیت بالا بوده. فرق و برتری اول این پروژه نسبت به کارهای دیگر همینه.


این نمونه بررسی کن میتونه برات یه ایده خوب باشه !از چه نظر؟ سطح دسترسی رو میگی؟
چون حجم کدش که خیلی کمتر از پروژهء بنده است. نه اینکه بگم حجم کد به خودی خودش چیزی رو ثابت میکنه، اما بنا به دانش و تجربهء بنده تا اینجا، یک چنین پروژه ای با الگوریتم و امکانات کامل و دقیق و همچنین امنیت بالا رو با این حجم کد عمرا نمیشه درست کرد.

wallfa
دوشنبه 04 اردیبهشت 1391, 15:58 عصر
من کاری به امنیت کار ندارم ، اما یه دنگاه بهش بندازی بد نیست !
چون سیستم خیلی خوبیه ، خیلی چیز که به نظر میرسه در نظر گرفته یه جور الگوریتم پیده سازی سطح دسترسی در سی ++ استفاده کرده و توان کلاسها به کار گرفته !
من که حیرون کارشم ، اما به امنیتش توجه نکردم ! چون کار امنیتی تا حالا انجام ندادم !

eshpilen
دوشنبه 04 اردیبهشت 1391, 17:14 عصر
دیتابیسش رو نصب کردم و برنامش رو دیدم.
منکه متوجه نشدم کجاش چرا چه برجستگی مهمی داره از دید شما که شما رو حیرون کرده!!
اینکه خیلی ناقصه. هیچی درست و حسابی نداره اصلا.
چه ربطی به سی++ داره اونوقت؟!

eshpilen
دوشنبه 04 اردیبهشت 1391, 17:52 عصر
البته استفاده از کلاس و اینها که خوبه. به شرطی که الگوریتم و کد کامل و قوی توش بذارید، وگرنه اینا به خودی خودش فراتر از یک پوسته نمیره. مثل همین پروژه ای که شما گذاشتید. اصلا شبیه شوخیه! مثلا کجاش چه امکانات کامل و بعد چه امنیتی داره؟ بقول معروف میگن مورچه چیه که کله پاچش چی باشه.
منکه الان دو یوزر با ایمیل یکسان درش ثبت کردم.
Forgot Password اش هم که جالبه. یوزرنیم رو میدی و پسورد رو عوض و ایمیل میکنه ظاهرا!!
بعدش اون فرم ثبت نامش چیه!! نه تکرار فیلد پسورد و ایمیل داره نه کپچا نه چیز دیگه.
جای دیگش هم چیزی ندیدم. خیلی ناقص تر از این حرفهاست.
سکیوریتی هم که اصلا حرفش رو نزن. از من میپرسی همینطوریش معلومه که اصلا درحد قابل استفاده نیست (البته اگر نظر نظر متخصص و این کاره باشه).
اصلا سشن رو هم باید انداخت دور. من تازه با سیستم رمزگذاری قوی ای که روش گذاشتم برای احراز هویت ازش استفاده نکردم. بدرد این کارها نمیخوره چون ضعف و ناپایداری زیاد داره و بطور کلی ارتباط و هماهنگی اون با دیتابیس و بقیهء بخشهای برنامه هم در نهایت دچار پیچیدگی و هزینهء نامعقولی میشه (من اول از سشن هم استفاده کرده بودم که در نهایت مجبور شدم کلا حذفش کنم).

شیء گرایی یا چیزهایی مثل MVC خوبن. ولی پروژهء بنده اینقدر حجیم و پیچیده است که فقط رسیدن به یک تصور و طرح اولیه در اینباره خودش کلی تحلیل و تفکر میطلبه. بخاطر همین اصلا توی این وادی نرفتم چون اینطوری الان احتمالا پروژم هنوز به نصف هم نرسیده بود و چند بار کلی از بخشهاش رو تغییر داده بودم بخاطر طراحی و پیاده سازی کلاس و MVC و این حرفا، درحالیکه الان به خوبی کار میکنه و از نظر امکانات چشمگیره و از نظر امنیت هم که میتونم بگم در سطح پروفشنال جهانیه (شاید یکی از قویترین کارهای بازمتن موجود). اینا رو الکی نمیگم. روی هر بخشش کلی کار و تحقیق بعلاوهء سالها مطالعات منابع سطح بالای امنیتی هست. سیستم تولید اعداد رندوم ده ها برابر قویتر از روشهای متداول برنامه نویسان دیگه داره، سیستم هش امنیتی با رعایت تمام اصول پایه، سیستم رمزگذاری سشن که تمامش فکر خودم بود و به نتایج جالبی انجامید که تاحالا جایی حتی اشاره ای هم به چنین روش و خواصی ندیدم، و ابتکارها و جزییات ظریف دیگه و جلوگیری از حمله های مختلف که در کمتر پروژه ای همشون لحاظ شدن. سعی کردم از بیش از یک لایهء امنیتی در هر جایی که میتونم استفاده کنم. مثلا سشن رو حتی اگر رمز هم نکنی باز تقریبا سوء استفاده ای ازش نمیشه کرد، چون اطلاعات حساس داخلش با salt و غیره هش شدن و بصورت خام ذخیره نمیشن.

ضمنا منکه کدهای خودم رو خیلی خوانا می یابم. حالا نمیدونم شاید بخاطر این باشه که پروژهء خودمه. اما در ضمن بارها در جاهای مختلف مطالبی راجع به اینکه دربارهء بعضی چیزها مثل شیء گرایی زیاد اغراق شده و همه جا هم نوشدارو نیست خوندم که بعید نیست درست باشن. خیلی وقتا احساس میکنی شیء گرایی کار رو بیشتر حجیم و پیچیده میکنه تا اینکه مزیت بزرگی داشته باشه، یا حداقل اینطور بگیم که هرجایی و برای هرکاری هزینهء طراحی و پیاده سازیش و بعضی مشکلاتی که ممکنه خودش پیش بیاره صرف نمیکنه. بنده هر قطعه کد دارای کاربرد مشترک یا دارای عملیات منطقی یا فنی کم و بیش مستقل رو توی یک فایل جداگانه گذاشتم و اسم فایلها هم خیلی خواناست و Trace کردن کد و فهمیدن طرز کارش هم بنظرم راحته (البته الگوریتم های برنامه بخاطر کمال و دقت و امنیت بالاش حجیم و پیچیده است که این یه مسئلهء اجتناب ناپذیر در سطح خودشه و لزوما به مسائل سطح بالاتری مثل شیء گرایی ارتباط نداره).

eshpilen
شنبه 09 اردیبهشت 1391, 00:28 صبح
نسخهء 7.5 آماده و ضمیمه پست اول تاپیک شد.

در این نسخه:

- اگر کانکشن HTTPS باشه فلگ secure برای تمام کوکی های برنامه (نه تنها کوکی سشن) ست میشه. این باعث میشه که کوکی هایی که از طریق HTTPS ست شدن هیچوقت از طریق HTTP معمولی ارسال نشن. یعنی مطمئن باشیم هیچوقت بصورت رمزگذاری نشده ارسال نمیشن. وگرنه چه این فلگ رو ست بکنیم و چه نکنیم بهرحال کوکی ها هم مثل بقیهء اطلاعات وقتی از طریق HTTPS ارسال بشن بصورت رمزگذاری شده و امن ارسال میشن.

- برای جایگزین $_SERVER['SCRIPT_NAME'] که یوشا گفت روی IIS ست نشده هم از دوتا متغییر دیگه کمک گرفتم. دیگه اگر اون دوتا هم ست نبودن نمیدونم باید چکار کرد، ولی فکر میکنم بالاخره 99% یا شاید اصلا 100% حداقل یکیش هرجایی باید ست باشه.

- session.use_trans_sid رو خاموش کردم تا یک وقت سشن آیدی در لینکها نشت نکنه.

- پیامهای خطای مربوط به دیتابیس که در یکی دو مورد یکسان/کلی و مبهم بود اصلاح شد.

- اینکه ممکنه تابع inet_pton حتی در بعضی نسخه های PHP5 هم در دسترس نباشه حل شد.

- موقع چک کردن ایجکسی نام کاربری در فرم ثبت نام موقعی که فرمت نام کاربری قابل قبول نباشه پیام خطای مناسب (Invalid) داده میشه بجای اینکه وجود نام کاربری در دیتابیس چک بشه.

--------------------------------

دیگه حال نداشتم زیاد تست کنم، تاجاییکه حوصله و چش و چال داشتم چک کردم که کدهای جدید و تغییرات خودشون باگ و مشکل جدیدی رو وارد نکرده باشن. دیگه خودتون برنامه رو تست کنید اگر مشکلی داشت بگید.

eshpilen
پنج شنبه 18 خرداد 1391, 19:10 عصر
نسخهء 0.7.7 منتشر میشود (به پست اول تاپیک ضمیمه شد).

خب یک کمبودی که در نسخه های قبلی بود عدم وجود امکان مشاهدهء اکانتهای کاربری ثبت شده در سیستم توسط ادمین بود، که نتیجتا مجبور بودیم از PhpMyAdmin برای این کار استفاده کنیم. پس گفتم این یک مورد رو هم به پروژه اضافه کنم بعنوان آخرین آیتم از حداقل امکانات.

ضمنا امکان حذف اکانتهای مورد نظر هم در صفحهء مشاهدهء اکانتهای کاربری توسط ادمین وجود داره.

امکانات Pagination کاملی هم برای این صفحه پیاده سازی کردم و این سیستم Pagination رو به صفحات دیگه مثل صفحهء نمایش اکانتهای منتظر تایید ادمین و صفحهء نمایش کاربران Ban شده هم اضافه کردم. علاوه بر لینکهای صفحات، امکان رفتن به صفحهء مورد نظر با وارد کردن شمارهء صفحهء نتایج هم وجود داره.

راستی امکان Sort بر اساس ستون مورد نظر هم در تمام این صفحات وجود داره. روی نام هر ستون که کلیک بشه نتایج بر اساس اون ستون مرتب میشن.

بجز این موارد یخورده تمیزکاری کد و مخلفات جزیی در بعضی جاهای دیگر کد هم انجام دادم.

کمبودی، نظری، ایده ای، انتقادی، پیشنهادی چیزی داشتید مطرح کنید.

در اسکرین شاتی که ضمیمه کردم صفحهء نمایش اکانتهای موجود در سیستم رو با امکاناتش مشاهده میکنید.
البته اکانتهایی که در تصویر دیده میشه فقط برای تست و بصورت خودکار توسط یک اسکریپت تولید شدن و بخاطر همین اطلاعات اکانتهای مشاهده شده، یکسری عبارتهای بی معنا و رندوم هست.

ضمنا پروژه رو روی github هم گذاشتم و در مراحل توسعهء اخیر ازش استفاده کردم: https://github.com/ferchang/reg8log
البته این آخرین نسخهء پروژه الان در برنچ dev هست (و نه در برنچ اصلی/master)، ولی احتمالا بعدا merge میکنمش با branch اصلی و اون موقع dev رو شاید حذف کنم.

eshpilen
سه شنبه 09 آبان 1391, 08:24 صبح
نسخهء 1.0 سیستم رجیستر و لاگین منتشر میشود!
در این نسخه علاوه بر کشف و رفع یکسری باگ (امنیتی و غیرامنیتی) و یکسری بهبودها/بهینه سازی ها، امکانات زیر اضافه شدن:

- الان تنظیمات سیستم محافظت از اکانتها دربرابر Brute-force برای اکانت ادمین و اکانت کاربران عادی کاملا از هم جدا هستن. این باعث انعطاف زیادی میشه و میتونیم سیستم قفل بر اساس اکانت و IP رو برای ادمین و کاربران عادی بطور کاملا مستقل فعال و غیرفعال کنیم و تنظیم پارامترهای اونها هم از هم کاملا جدا هستند. منظورم از پارامترها، تنظیم فعال و غیرفعال بودن قفل بر اساس اکانت یا IP، تنظیم تعداد لاگین اشتباهی که بعد از اون کپچا نیازه، تنظیم تعداد لاگین اشتباهی که بعد از اون اکانت و/یا IP قفل میشه، و بازهء زمانی ای که در اون حداکثر تعداد لاگین اشتباه تعیین شده رو میشه داشت هست.

- سیستم Block-bypass (سیستمی که کاربری که امکان لاگین کردن رو به علت قفل شدن اکانتش از دست داده میتونه با ارسال لینک مخصوصی به ایمیلش ازش برای لاگین استفاده کنه) رو هم الان میشه فقط برای ادمین یا فقط برای کاربران عادی یا برای هر دو فعال کرد. اینم آخر انعطاف!!

- از خیلی پیشتر در این فکر بودم که تعداد لاگین ناموفق حتی در حالت Block-bypass باید محدود بشه، منتها قبلا بخاطر کاهش حجم و فشار کار این خصوصیت رو پیاده سازی نکردم. الان این امکان وجود داره که برای تعداد لاگین ناموفق در حالت Block-bypass هم محدودیت تعیین کرد.
فرض کنید مثلا هکری ایمیل کسی رو هک کرده، اما میخواد پسورد واقعی اکانت کاربر رو در یک سایتی که کاربر عضوش هست به هر دلیلی کشف کنه (مثلا میخواد دسترسی مخفیانه به اکانت کاربر در اون سایت داشته باشه). اگر محدودیتی روی تعداد لاگین ناموفق در حالت Block-bypass نباشه، هکر میتونه از سیستم Block-bypass برای تست دستی حدسهاش یا Brute-force سنگین تر با استفاده از برنامه های خودکار، سوء استفاده کنه.

- امکان دیگری که اضافه کردم اینه که الان میشه از سیستم Block-bypass برای دور زدن قفل IP هم استفاده کرد (قبلا فقط برای دور زدن قفل اکانت بود). البته این امکان هم قابل فعال و غیرفعال کردن است.
فرضا کاربری که به سایت مراجعه میکنه اما بخاطر اینکه کس دیگری از همون IP اقدام به Brute-force روی بخش لاگین سایت کرده بوده و اون IP حالا برای مدتی بلاک شده، حالا میتونه درصورت نیاز با استفاده از سیستم Block-bypass به اکانت خودش لاگین کنه.
میدونید که استفادهء چند نفر از یک IP بصورت همزمان یا با فاصلهء زمانی نسبتا کم، امر بعیدی نیست.

- امکان دیگر اضافه شده اینه که ادمین میتونه این اختیار رو به کاربران بده که سیستم قفل اکانت و قفل IP رو برای اکانت خودشون غیرفعال کنن. اینم باز نهایت انعطاف و قابلیت پیکربندی برای تقریبا هر شرایطی پیشبینی شده و نشده ای هست که در پروژه گذاشتم. البته این قابلیت رو بصورت پیشفرض خاموش گذاشتم و بنظرم تا نیاز واقعی پیش نیاد نباید فعالش کرد. ضمنا میشه تعیین کرد که کاربران بتونن قفل اکانت، قفل IP، و یا هردو رو برای اکانت خودشون فعال و غیرفعال کنن (البته اکانت ادمین از تمام محدودیتها بر روی این تنظیم مستثنی است). البته این تنظیمات نمیتونن تنظیمات موجود در فایل کانفیگ (config_brute_force_protection.php) رو Override کنن. این تنظیمات در سطح بعد از تنظیمات فایل کانفیگ عمل میکنن. یعنی مثلا اگر تنظیم سیستم قفل IP در فایل کانفیگ برابر خاموش باشه، کاربران (و همینطور ادمین) نمیتونن برای اکانت خودشون قفل IP رو فعال (یا غیرفعال) کنن، چون این سیستم برای کل سایت خاموش تعیین شده. گزینه هایی هم که در صفحهء تنظیم به کاربران نمایش داده میشن بر اساس تنظیمات فعلی فایل کانفیگ هستند.
ضمنا یک ویژگی دیگری که در این سیستم گذاشتم اینه که، اگر بعد از تنظیمات کاربران، تنظیمات فایل کانفیگ تغییر کنن، سیستم بصورت هوشمندانه ای تنظیمات جدیدی رو تعیین میکنه تا مقدار حفاظت از اکانت کاربر کم نشه (اما میتونه زیاد بشه). مثال: فرض کنید هر دوی سیستم قفل اکانت و قفل آیپی در فایل کانفیگ فعال باشن، فرض کنید کاربران اجازهء غیرفعال کردن هردو رو برای اکانت خودشون دارن، فرض کنید کاربری میاد و قفل اکانت رو برای اکانت خودش غیرفعال میکنه؛ در این صورت، اکانت این کاربر هنوز توسط سیستم قفل IP مورد محافظتی گرچه کمتر از محافظتی که قفل اکانت ایجاد میکنه قرار میگیره (که کاربر هم احتمالا این رو میدونه و روش اتکا کرده). حالا ادمین بعدا میاد و سیستم قفل IP رو در فایل کانفیگ خاموش میکنه. حالا اکانت اون کاربر هیچ محافظتی دربرابر Brute-force نداره! ولی سیستم میاد و خودش بصورت خودکار این پایین آمدن درجهء حفاظت رو تشخیص میده، و سیستم قفل اکانت رو برای اون کاربر فعال میکنه.
طراحی و پیاده سازی این سیستم که به کاربران امکان تعییر تنظیمات سیستم ضد Brute-force برای اکانت خودشون رو میده پیچیده بود و حجم کاری قابل توجهی داشت، اما بهرحال فکر کردم بهتره وجود داشته باشه و شاید نیاز بشه. بعدش هم که باید تبعاتش رو درنظر میگرفتم و اصولی طراحی میشد تا برعکس باعث کاهش امنیت نشه؛ بخاطر همین مجبور شدم الگوریتمش رو کامل و هوشمند کنم.

- قبلا گفته بودم و در فکرش بودم که یک جوری جلوی سوء استفاده از سیستم ایجکس چک کردن ثبت شده بودن نامهای کاربری رو که در بخش ثبت نام سایت استفاده میشه بگیرم؛ چون از این سیستم خیلی راحت و سریع میشه برای تست موجود بودن نامهای کاربری در سایت استفاده کرد (که نمونهء متداولی از Information leakage است). البته احتمالا ما نمیتونیم جلوی این رو 100% بگیریم، اما میشه تاحد قابل توجهی محدود/دشوارش کرد. بنابراین بنده یک محدودیت قابل تنظیم در تعداد استفاده از این سیستم به ازای هر IP در یک بازهء زمانی مشخص گذاشتم که میشه فعال و غیرفعال و تعدادش (و بازهء زمانی) رو تنظیم کرد. ضمنا این امکان هم وجود داره که اگر از یک IP یک ثبت نام موفق صورت گرفت، که به معنای پاس کردن تست کپچا است (که معمولا بدین معناست که طرف مقابل روبات نیست)، تعداد استفاده از سیستم ایجکس برای اون IP توسط اون کلاینت ریست بشه تا جلوی استفاده های بعدی یا کاربران احتمالی بعدی اون IP از این سیستم بی دلیل سد نشه. البته این کار با ذخیرهء یک کوکی در مرورگر کاربر انجام میشه تا مطمئن باشیم فقط تعداد استفاده های همون کاربر رو کاهش دادیم.

- سیستم لاگ کردن وقایع قفل شدن اکانت و IP رو هم که در پست قبلی گفته بودم طراحی و پیاده سازی کردم. مشتمل بر امکان آگاه سازی ادمین از طریق ایمیل و/یا موقعی که در سایت فعالیت میکنه. این سیستم هم انعطاف خوبی داره و تنظیمات متعددی برای پارامترهای مختلف اون گنجانده شدن. مثلا میشه تعیین کرد که فقط موقعی که حمله نسبت به اکانت ادمین بوده به ادمین خبر داده بشه. یا میشه تعیین کرد که وقتی تعداد حمله ها در 24 ساعت به تعداد خاصی رسید ادمین رو خبر کنه. همینطور میشه تعیین کرد که فاصلهء زمانی ارسال ایمیل ها کمتر از یک حدی نباشه (مثلا اگر حمله های زیادی صورت میگیره که باعث میشه ایمیل های زیادی با فاصلهء زمانی کم به ایمیل ادمین ارسال بشن و این امر ایجاد مشکل میکنه). ضمنا بخاطر اهمیت اکانت ادمین، میشه اکانت ادمین رو از این محدودیتها مستنثنی کرد.

- امکان تغییر کلید لاگین کاربر موقعی که لاگ آوت میکنه رو به برنامه اضافه کردم.
تغییر کلید لاگین (که در کوکی احراز هویت خودکار ذخیره میشه) موقع لاگ آوت باعث میشه که تمام سیستمها/افراد دیگری که ممکنه در اکانت کاربر لاگین باشن، از لاگین خارج بشن. این برای امنیت خیلی خوب بنظر میرسه!

- امکان Logging فعالیت های کاربران رو هم اضافه کردم که میشه هرکدام رو جداگانه فعال و غیرفعال کرد: فعالیت در سایت، لاگین، لاگ آوت.
البته فقط زمان آخرین این فعالیت ها برای هرکاربری ثبت میشه (در همون جدول accounts و در رکورد مربوطه هر کاربر).
این اطلاعات رو ادمین میتونه در صفحه ای که مشخصات اکانتهای ثبت شده در سیستم رو نشون میده مشاهده کنه.

خب این بود امکانات جدید برنامه!
البته همینا رو هم ممکنه دیر یا زود تغییراتی بدم، ولی فکر کردم وقت منتشر کردن امکانات اضافه شده و اصلاحات انجام شده رسیده. چون با تغییرات جدید نیاز به تست و دیباگ جدید هم پیدا میشه و دوباره کلی مراحل و زمان میبره.

اگر باگی چیزی دیدید یا فیدبک دیگری داشتید حتما مطرح کنید.

ضمنا برنامه رو روی هاست واقعی در اینترنت آپلود و تست کردم. یکی دوتا اشکال کوچک بوجود آمد که روی لوکال وجود نداشتن (اونایی که یادمه: تصویر کپچا و لینک لاگ آوت کار نمیکردن؛ هردوشون هم به ریزه کاریهایی در آدرس دهی ربط داشتن)؛ اشکالات رو برطرف کردم. الان میشه گفت برنامه روی هاست واقعی و تحت لینوکس هم تست شده؛ البته تست واقعا جزیی و کاملی نکردم ولی کارکردهای پایه بی نقص بنظر میرسیدن. یکی دوتا باگ هم همونجا دیدم که درست کردم.

خلاصه برنامه هست و دیباگ و تکامل!
هنوز Stable نیستا :لبخند:

eshpilen
شنبه 04 آذر 1391, 20:27 عصر
نسخهء 1.3 منتشر میشود.

امکانات جدید در این نسخه:

- میشه تعیین کرد که موقعی که کسی رجیستر میکنه، با ایمیل به ادمین اطلاع داده بشه. این امکان بخصوص در مواقعی که رجیسترها نیاز به تایید شدن دستی توسط ادمین هم دارن میتونه خیلی مفید باشه. تنظیماتش هم مثل همیشه دارای انعطاف زیادیه (کامنت های فایل کانفیگ رو بخونید متوجه میشید).
- یکسری آمار راجع به مثلا تعداد اکانتهای رجیستر شده، تعداد اکانتهای و آیپی های بلاک شده و اینا حالا در همون صفحهء مدیریت ادمین در جلوی گزینه ها نمایش داده میشن. البته این گزینه رو میشه فعال و غیرفعال کرد (گفتم شاید در شرایطی به مشکل پرفورمنس بخوره و لود صفحه زیادی کند بشه).
- یه امکان جدید به سیستم اضافه کردم و اونم اینه که میشه لاگین (و در نتیجه کلید ذخیره شده در کوکی autologin) رو وابسته به IP کرد.
طبیعتا این کار منجر به امنیت افزوده میشه. حتی اگر کسی کوکی احراز هویت کاربر رو سرقت کنه، نمیتونه از IP دیگری خودش رو بجای کاربر احراز هویت کنه.
این سیستم هم تنظیماتش باز آخر انعطاف هست. مثلا میشه تعیین کرد که فقط برای ادمین اینطور باشه، یا برای کاربران عادی، یا برای همه.
ضمنا یک آپشن هم گذاشتم که اگر فعال بشه اصلا کاربران میتونن بدون توجه به تنظیم قبلی، خودشون موقع لاگین تعیین بکنن که لاگین اونها به IP شون وابسته بشه یا نه.
- الان اون سیستم لاگ آوت با امنیت بیشتر رو هم که قبلا دربارش بحث کرده بودم پیاده سازی کردم. یعنی سیستم طوری هست که به محض کلیک کاربر روی لینک لاگ آوت، کاربر رو لاگ آوت میکنه. یعنی حتی اگر اینترنت طرف قطع شده باشه یا سرور سایت در اون موقع مشکل داشته باشه، کاربر میتونه خیالش راحت باشه که لاگ آوت شده و نیازی به پاک کردن دستی کوکی های سایت نیست (البته خیلی کاربران که اصولا از این چیزا اطلاعات کافی ندارن برای امنیت اون دسته هم این امکان خیلی خوبه).
در عین حال سیستم میتونه لاگ آوت کاربران رو لاگ کنه. چون حالا سیستم از دوتا کوکی وابسته به هم برای احراز هویت استفاده میکنه که محتویات یکیش موقع لاگ آوت توسط جاوااسکریپت پاک میشه، ولی هنوز در سمت سرور میشه با کوکی دیگر کاربر رو شناسایی کرد (ولی بدون وجود و صحت کوکی دیگر، کاربر رو لاگین نمیکنیم).

یکسری باگهای امنیتی و غیرامنیتی رو هم کشف و برطرف کردم.
بخصوص سیستم بلاک IP رو یه تغییرات مهمی دادم، چون بنظرم سیستم قبلی قابل سوء استفاده بود.
سیستم قبلی برای جلوگیری از بلاک شدن IP هایی که بصورت مشترک توسط عده ای استفاده میشن میامد و نسبت تعداد لاگین های ناموفق به موفق رو درنظر میگرفت. البته در این سیستم هر تعداد لاگین موفق به یک اکانت فقط یک بار شمرده میشد تا به این طریق کسی نتونه سوء استفاده کنه و به ازای هر بار تلاش ناموفق یک بار به اکانتی که خودش رجیستر کرده لاگین کنه. اما این سیستم هنوزم یک ضعفی داشت و اون اینکه اگر مثلا هکر 100 اکانت در سیستم رجیستر میکرد اونوقت میتونست از هر آیپی 100 برابر حالت مجاز تلاش لاگین ناموفق داشته باشه.
سیستم فعلی دیگه اون طوری نیست و به روش Proportional عمل نمیکنه. ولی خب کار برنامه نویسیش بیشتر و پیچیده تر شد چون هم میخواستم مشکلی برای کاربران ایجاد نکنه و یوزرفرندلی هم باشه و هم امنیت کافی داشته باشه و به هیچ وجه قابل دور زدن نباشه.

یک نکته ای رو باید توجه کنید در سیستمهای بلاک این پروژه و اونم اینه که فرضا اگر شما 3 بار تلاش لاگین ناموفق به اکانت خودتون داشته باشید و در بار چهارم موفق به لاگین بشید، اون 3 تلاش ناموفق قبلیتون از سیستم حذف میشن (چون مشخص میشه که جهت حمله نبودن). این نظر یوزرفرندلی و جلوگیری از مشکلاتی هست که در غیراینصورت ممکنه پیش بیان. سیستم بلاک IP مشابه همین روش رو داره ولی طراحی و پیاده سازیش پیچیده تر بود.
البته اینم بگم که این زیرسیستم ریزه کاریهای مهمی داره که باید درنظر گرفته بشن تا خودش راهی برای سوء استفاده و دور زدن سیستم ضد Brute-force نشه.

یه ریزه کاریها و حمله های پیچیده ای رو در این پروژه درنظر گرفتم که به فکر کسی نمیرسه؛ چون میدونم شدنی هستند (ولو با نیاز به یک هکر دانشمند و کلی برنامه نویسی سفارشی).

این نسخهء برنامه رو تاحدی که حوصله داشتم و برام اولویت داشت روی لوکال و اینترنت و در FF و IE تست و رفع باگ کردم، ولی بعید نیست بخاطر کدهای تغییر کرده و افزوده ای که داره هنوزم باگهایی توش باشن که از زیر دستم در رفته باشن. اگر موردی دیدید لطفا گزارش کنید تا برطرف کنم.

eshpilen
پنج شنبه 12 بهمن 1391, 22:16 عصر
نسخهء 1.5 منتشر میشود.

امکانات افزوده شده در این نسخه:

- افزودن متغییر کانفیگ registerations_alert_threshold_period.
با این متغییر میتونیم محدودهء زمانی ای رو که registerations_alert_threshold در اون مدت بررسی میشه تعیین کنیم.
مثلا اگر registerations_alert_threshold برابر 10 باشه و registerations_alert_threshold_period برابر 3600، اگر تعداد ثبت نامها در یک ساعت به 10 عدد برسه، به ادمین اطلاع داده میشه (با ایمیل یا موقع لاگین یا هردو برحسب تنظیم متغییر کانفیگ مربوطه).

- افزودن متغییر کانفیگ max_registeration_alert_emails و max_registeration_alert_emails_period.
با این متغییرها میشه تعیین کرد که در محدودهء زمانی مشخصی حداکثر تعداد مشخصی ایمیل جهت اطلاع ثبت نامها بتونه به ادمین ارسال بشه، و نه بیشتر.

- افزودن متغییر کانفیگ account_blocks_alert_threshold_period.
با این متغییر محدودهء زمانی ای رو که account_blocks_alert_threshold در اون محدودهء زمانی بررسی میشه مشخص میکنیم.
یعنی بطور مثال میتونیم مشخص کنیم که اگر در عرض یک ساعت 20 مورد بلاک اکانت داشتیم، به ادمین اطلاع داده بشه.
قبلا محدودهء زمانی قابل تنظیم نبود و روی 24 ساعت hardcode شده بود.

- ip_blocks_alert_threshold_period.
این متغییر هم مثل متغییر قبلی است منتها برای تعداد بلاکهای IP که با ip_blocks_alert_threshold مشخص میشه.

- افزودن متغییرهای کانفیگ max_alert_emails و max_alert_emails_period.
با این متغییرها میشه تعیین کرد که در محدودهء زمانی مشخصی حداکثر تعداد مشخصی ایمیل هشدار امنیتی (مربوط به سیستمهای بلاک اکانت و بلاک IP) برای ادمین قابل ارسال باشه.

خب امیدوارم موردی از قلم نیفتاده باشه.

شاید این آخرین نسخه از این پروژه باشه که منتشر میکنم یا حداقل در کوتاه مدت دیگه آپدیتش نکنم؛ چون تا الان روی این پروژه وقت و انرژی زیادی گذاشتم و دیگه تمایل ندارم بیشتر از این روش تمرکز کنم. یعنی دیگه برام اولویت نداره و توی فکر هستم که پروژهء بعدی رو انتخاب کنم (که ممکنه اصلا در حیطهء دیگری غیر از وب باشه) یا هرکار دیگری مثل یادگیری چیزهای جدید.
قبلا توی فکر بودم نسخهء فارسیش رو هم بسازم/دوزبانه کنم؛ ولی حتی انگیزهء کافی برای انجام این رو هم ندارم فعلا و بنظرم عاقلانه نیست بیش از این روی چیزی وقت بذارم که هنوز برای خودم کاربرد عملی نداره.
فکر میکنم این پروژه تا همین الانش هم بقدر کافی برجسته باشه از نظر گستردگی امکانات، انعطاف و میزان کانفیگ بسیار زیادی که داره و میشه با شرایط و نیازهای مختلف تطبیقش داد، امنیت و مکانیزم های رمزنگاری که درش استفاده شده، و دقت و کمال منطق و الگوریتم که باعث استحکام زیاد اون میشن.
البته همونطور که بارها گفتم، این سیستم رو برای کاربردهای با تعداد کاربر/ترافیک زیاد طراحی نکردم و بنابراین در این زمینه هیچ تضمینی نمیدم (از نظر مقیاس من یه چیزی توی مایه های حداکثر 100 هزار کاربر توی ذهنم بود، و از نظر ترافیک هم قطعا نه یک سایت خیلی شلوغی که در اکثر اوقات کاربران همزمان زیادی داره (ولی عددی رو حتی بصورت تخمینی نمیتونم مشخص کنم!)).

راستی تست سراسری مجدد روی این نسخه انجام ندادم. فقط بخشهایی رو که اضافه کردم/تغییر دادم بصورت موردی تست کردم. اگر باگی چیزی مشاهده کردید گزارش کنید.

eshpilen
پنج شنبه 01 فروردین 1392, 19:46 عصر
نسخهء 1.8 ارائه میشود.

اساسا این نسخه بخاطر دو زبانه کردن پروژه بود (اضافه کردن زبان فارسی)، ولی تعدادی باگ هم کشف و رفع شده و یک مقداری بهبود و امکانات بیشتر هم صورت گرفت.

البته خوشبختانه باگها اکثرا امنیتی نبودن.

البته در بخشهای مربوط به ادمین از نظر SQL Injection تنبلی و کم کاری کرده بودم با این فرض که ادمین مالک سایت هم هست و معنی نداره به سایتی که کامل زیر دست خودشه حمله کنه؛ ولی بعد فکر کردم این فرض لزوما درست نیست که ادمین برنامه ادمین خود هاست هم هست! مثلا ممکنه ما بعنوان مالک سایت برنامه رو نصب کنیم و بعد مشخصات ورود به اکانت ادمین رو بدیم به کس دیگه تا اون ادمین سیستم باشه.
خوشبختانه در بخشهای ادمین کار خیلی کمی نیاز بود تا در برابر SQL Injection امن بشه.

سیستم ضد CSRF رو هم یخورده قوی تر کردم؛ یک توکن رو دو توکن کردم که یکی برای درخواستهای GET و دیگری برای درخواستهای POST استفاده بشه. اینطور اگر توکن درخواستهای GET دست دیگران بیفته (چون دیتای موجود در Query string امنیت کمتری داره نسبت به دیتاهایی که در فیلدهای فرمها با درخواستهای POST منتقل میشن)، امنیت درخواستهای POST همچنان محفوظ میمونه. معمولا هم عملیات مهم که بخصوص در سمت سرور تغییر ایجاد میکنن با POST انجام میشن (حداقل از نظر اصولش باید اینطور باشه).

متد درخواستهای ایجکس رو هم از GET به POST تغییر دادم که اصول و امنیتش بهتر رعایت شده باشه. حداقل از نظر احتیاط ضرر نداره.

امکان دیگر هم که اضافه کردم، گزینهء لیست و مشخصات اکانتهای منتظر تایید شدن ایمیل با لینک فعال سازی است، که در اون صفحه ادمین میتونه اگر خواست هرکدام رو حذف هم بکنه (البته قاعدتا نباید این کار رو بکنه/نیازی نیست، ولی بهرحال امکانش رو گذاشتم چون برای توسعه و تست هم مفیده).

یک اشتباه ضایع هم در بخش سیستم بلاک IP (ضد Brute-force) وجود داشت که برطرف کردم.
اشکال این بود که تنظیمات سیستم قفل IP برای ورود به اکانت ادمین و کاربران معمولی جداست، ولی در عمل اینا قاطی هم میشدن. موقع تست های قبلی متوجه این قضیه نشده بودم!

این نسخه رو هم میتونید بررسی کنید و اگر باگی داشت گزارش بدید؛ من میخواستم تست کامل بکنم اما دیگه وقت و حوصلش رو نداشتم و ضمنا تغییر اساسی ای خاصی هم غیر از این باگها که برطرف و تست کردم توی برنامه نیست بجز فارسی سازی، که اونم تستش زیاد ضرورت نداره و همون موقع انجام و درج ترجمه ها روی هر مورد تست هم انجام دادم.

الان برنامه از همون اول و بخش نصب دیتابیس میتونه فارسی بشه. البته یادتون نره اول دیتابیس خالی برنامه رو (دیتابیسی با نام reg8log) باید بصورت دستی ایجاد کنید.

تغییر زبان در هر لحظه میتونه توسط گزینه ای که در صفحات درج کردم براحتی صورت بگیره.

این متغییرها به فایل اینکلودی common.php اضافه شدن که مربوط به زبان پیشفرض هستند:

متغییر lang: این متغییر زبان پیشفرض سیستم رو مشخص میکنه. درحال حاضر فقط دو مقدار en و fa قابل استفاده هستند.

متغییر admin_emails_lang: زبان ایمیل های آگاه سازی ارسالی به ادمین رو مشخص میکنه. اگر مقدارش خالی باشه، از مقدار متغییر lang بجاش استفاده میشه.

ضمنا دقت داشته باشید هر کاربر با هر زبانی که موقع ثبت نام انتخاب کرده باشه، ایمیل های آگاه سازی درمورد مراحل بعدی ثبت نام (منجمله آگاه سازی درمورد رد یا تایید ثبت نام توسط ادمین) با همون زبان بهش ارسال میشن.

eshpilen
جمعه 02 فروردین 1392, 11:35 صبح
نظرتون چیه؟ :متفکر:
مدتهاست ملت فقط دانلود میکنن و نهایت یه تشکر هم میزنن، ولی چیزی نمیگن!

خب الان پروژه فارسی هم که داره.
تنها ضعف و نقص هاش فکر کنم این باشه که شیء گرایی نداره و الگوی طراحی هم که نداره و طوری هم نیست که دیگران بتونن براحتی اون رو با برنامه های خودشون Integrate کنن.
من فکر کنم از نظر کاربردی این گزینهء آخر (قابلیت Integrate کردن) مهمتر باشه. حالا شیء گرایی و الگوی طراحی رو سر فرصت و برحسب نیاز میشه انجام داد، چون بدون اونا هم برنامه کار میکنه.

البته شیء گرایی و اینا میتونه به قابلیت Integrate کردن هم ربط مستقیم داشته باشه، ولی من فکر کنم بغیر از شیء گرایی راههای دیگری هم براش باشه.
مثلا برای جلوگیری از تداخل نامی متغییرهای برنامه، میشه یک پیشوند یکتایی رو به همهء متغییرها اضافه کرد. فکر کنم این کار از تغییر ساختار کلی برنامه راحتتر باشه!

2undercover
جمعه 02 فروردین 1392, 12:13 عصر
موقع نصب جدول های SQL بعد از نصب با موفقیت این خطا رو میده:
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\reg8log\setup\db_setup.php:53) in C:\xampp\htdocs\reg8log\include\class\class_cookie .php on line 71

یه چیز دیگه شما قرار شده زبان فارسی اضافه کنی پس باید از واژه های فارسی استفاده بشه :چشمک::چشمک::چشمک:(مثال : لاگین => ورود...یا اکانت ها => حساب ها)

eshpilen
شنبه 03 فروردین 1392, 14:51 عصر
موقع نصب جدول های SQL بعد از نصب با موفقیت این خطا رو میده:
Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\reg8log\setup\db_setup.php:53) in C:\xampp\htdocs\reg8log\include\class\class_cookie .php on line 71
آره درسته. بخاطر اینه که آخر کار (بعد از کلی خروجی دادن) یک کوکی ست میکنم.
در تستهای خودم این خطا رو نمیده و بنابراین متوجه نشده بودم.
البته این کوکی کاری که انجام میده ست نشدنش مهم نیست.

برای رفع این باگ، به اوایل فایل db_setup.php این رو اضافه کنید:

ob_start();
مثلا من در خط 15 اضافه کردمش.

2undercover
شنبه 03 فروردین 1392, 16:54 عصر
می دونستم که باید این کار رو بکنم فقط به خاطر اینکه در جریان باشید گفتم! ;)

eshpilen
شنبه 07 دی 1392, 10:01 صبح
نسخهء 2 آماده شد.

در این نسخه:

- چندتا باگ رفع شد.
بعضی باگها یه مقدار امنیتی هم بودن (نه در حد وخیم).

- اضافه شدن کپچا به فرم لاگین بصورت دینامیک.
بعد از اینکه یک نام کاربری رو در فرم لاگین وارد میکنید، بوسیلهء ایجکس از سمت سرور چک میشه که آیا برای لاگین به اون اکانت نیاز به کپچا هست یا نه، اگر بود اونوقت کپچا همون موقع بصورت دینامیک به فرم اضافه میشه و دیگه این داستان پیش نمیاد که کاربر یکبار فرم رو سابمیت کنه و فرم مجددا از سمت سرور با پیام خطایی که میگه نیاز به کپچا هم هست برگرده.

- چک شدن کپچا بصورت ایجکس در تمام موارد.
تمام فرمهایی که کپچا دارن، موقع فشردن دکمهء سابمیت، قبل از سابمیت شدن فرم صحت کد کپچای وارد شده توسط کاربر بصورت ایجکس با سرور چک میشه و اگر غلط باشه با پیام مناسب به اطلاع کاربر میرسه و فرم سابمیت نمیشه. یعنی دیگه نیازی نیست فرم یک بار به سمت سرور ارسال بشه و بخاطر خطا در کپچا مجددا با پیام خطا برگشت داده بشه که اونوقت احتمالا کاربر مجبور به زحمتی مثل وارد کردن مجدد پسوردش هم بشه.

- امکان بخاطرسپاری لاگین (گزینهء remember me) در این نسخه بصورت فوق العاده قابل کانفیگ و منعطفی در اومده. الان میتونیم تعیین کنیم که کاربران بتونن چند و چگونه گزینه های بخاطرسپاری در فرم لاگین داشته باشن. مثلا میتونیم بخاطرسپاری برای 5 دقیقه، یک ساعت، یک هفته، یک ماه، یک سال و غیره رو بصورت یک منو بجای چک باکس remember me که در نسخه های قبلی وجود داشت داشته باشیم.
این منو میتونه یک یا هر تعدادی گزینه داشته باشه.
ضمنا گزینه های بخاطرسپاری کاربران عادی و ادمین از هم کاملا جداست و میتونن هرکدام آپشن های کاملا متفاوتی داشته باشن. به این میگن آخر انعطاف و قابلیت پیکربندی!
این زمانهای بخاطرسپاری در سمت سرور هم چک میشن و بنابراین قابل دور زدن توسط کاربران در سمت کلاینت نیستن. بطور مثال شما میتونید کاربران رو مجبور کنید که بخاطرسپاری لاگین اونها بیش از 8 ساعت نباشه.
برای اطلاع بیشتر، متغییرهای کانفیگ autologin_ages و admin_autologin_ages در فایل config_identify.php رو نگاه کنید.

- امکان دیگر اضافه شده اینه که اگر یادتون باشه موقعی که ثبت نام صورت میگرفت، کاربر بصورت خودکار تا زمان باز بودن مرورگر لاگین میشد. البته این لاگین خودکار بعد از ثبت نام رو میشه با false کردن متغییر login_upon_register در فایل config_register.php غیرفعال کرد.
الان یک متغییر دیگر هم به این جریان اضافه کردم بنام login_upon_register_age که میتونید باهاش طول عمر این لاگین خودکار رو تعیین کنید. مثلا تعیین کنید که کاربر فقط برای یک ساعت لاگین بمونه، یا هر زمان دیگری که میخواید، مثلا تا همون باز بودن مرورگر.

- طول عمر لاگین خودکار هر کاربر موقع لاگین در دیتابیس ثبت میشه، و بعد در هر درخواست بر اساس کوکی لاگین خودکار، طول عمر لاگین خودکار کاربر در سمت سرور چک میشه که از زمان تعیین شده تجاوز نکرده باشه. اگر تجاوز کرده باشه، کاربر عملا لاگ آوت خواهد بود، هرچند که کوکی لاگین خودکار کاربر درست و زنده باشه.
این چک کردن سمت سرور از نظر امنیتی اهمیت داره و منجر به امنیت و اطمینان بیشتری میشه. چون بطور مثال درصورت سرقت کوکی، هکر نمیتونه به مدتی بیش از آنچه که توسط کاربر برای آن لاگین درنظر گرفته شده بوده از اون کوکی برای دسترسی به اکانت کاربر استفاده کنه. مثلا شاید کاربر گزینهء بخاطرسپاری لاگین رو 30 دقیقه تعیین کرده بوده، اگر کوکی لاگین کاربر سرقت شده باشه، و اگر در سمت سرور عمر این لاگین خودکار چک نشه، هکر میتونه تا زمان طولانی تری که میتونه بالقوه نامحدود باشه از این کوکی برای دسترسی به اکانت کاربر استفاده کنه.
ضمنا این چک کردن سمت سرور میتونه در موارد دیگری مثل بهم خوردن تنظیم تاریخ و ساعت کلاینت هم از نظر امنیتی مفید باشه و این قضیه پیش نیاد که برخلاف انتظار کاربر، لاگین خودکار مرورگرش بعد از زمان تعیین شده هم برقرار باشه.

- طول عمر لاگین های خودکار که تا باز بودن مرورگر برقرار هستن الان بوسیلهء متغییر max_session_autologin_age در فایل config_identify.php قابل محدود کردن است. بنده مقدار پیشفرض رو روی 12 ساعت تنظیم کردم.
این گزینه هم از نظر امنیتی اهمیت داشت، چون کوکی هایی که طول عمرشون به اندازهء باز بودن مرورگر تعیین میشه عملا محدودیت زمانی ندارن و این به دلایلی که در گزینهء قبلی توضیح دادم میتونه خطرناک باشه.
الان میتونید برای عمر اینطور لاگین ها یک حداکثر تعیین کنید. اگر مرورگر کاربر زودتر از این زمان بسته شد، کوکی پاک شده و لاگین خودکار از بین میره، و اگر مرورگر همینطور باز بمونه بازهم طول عمر لاگین خودکار نمیتونه از زمان تعیین شده بیشتر بشه، چون در سمت سرور چک میشه.

خب این از ویژگیهای این نسخه!
فقط این هست که این نسخه رو خیلی تست نکردم چون نه دیگه وقت داشتم نه حس و حال و اولویتش رو.
use at your own risk :لبخند:
ولی خب نه اینکه هیچ تستی نکرده باشم؛ تاجایی که بنظرم صرف میکرد (واسه خودم) تست و باگیابی و باگزدایی کردم.
اگر باگی چیزی دیدید گزارش کنید خب!

colors
دوشنبه 16 دی 1392, 22:25 عصر
آقا eshpilen این همه روش کار کردی, چرا داکیومنتش استاندارد نیست؟ الان خیلیها میگن داکیومنت نویسی حتی مهمتر از کد خوب هست؟

eshpilen
سه شنبه 17 دی 1392, 08:03 صبح
آقا eshpilen این همه روش کار کردی, چرا داکیومنتش استاندارد نیست؟ الان خیلیها میگن داکیومنت نویسی حتی مهمتر از کد خوب هست؟
چون پروژه شخصی بوده فقط واسه دل و کاربرد خودم نوشتم.
میدونید که داکیومنت نوشتن کار چندان جذابی نیست!
طبیعتا ما برنامه نویسان دوست داریم با حداکثر سرعت کد و برنامه بنویسیم.
ضمنا داکیومنت طبیعتا بهتره در یک مراحل پایانی برنامه باشه که دیگه زیاد تغییر و حذف و غیره نداشته باشه برنامه و وقت و انرژی ای که روی تهیه داکیومنت ها گذاشته شده هدر نره.
این پروژه اولین پروژه بنده در این زمینه بوده که تاحدی آزمایشی و تمرینی است و هنوز به تکامل و مراحل نهایی خودش نرسیده احتمالا. مثلا شاید یه زمانی بخوام بر اساس شیء گرایی ای تغییرش بدم. البته فقط شاید! چون فعلا که کار میکنه و واسه خودم نیاز و اولویت بیشتری پیش نیامده و وقت آزاد هم دیگه زیاد ندارم.

البته بنده متغییرهای کانفیگ برنامه رو یا توی فایل help یا توی خود فایلهای کانفیگ درحد خوبی کامنت گذاری کردم (به زبان انگلیسی البته) که فکر میکنم با خوندن اونا اگر طرف فنی باشه خیلی مسائل براش روشن میشه دربارهء طرز کار و امکانات برنامه و نیازهای کانفیگ که افراد ممکنه داشته باشن.
بهرحال واجب ترین چیز که حتی برای برنامه نویسی خودمم مفید یا لازم بود همین کامنت گذاری متغییرهای کانفیگ برنامه بود که اساسی هستن برای فهمیدن طرز کار و استفاده از برنامه.

راستی این نسخه اخیر که گذاشتم یک مورد باگ sql injection داشت :لبخند:
خوشبختانه زود خودم متوجه شدم و رفعش کردم.
ولی بازم ممکنه باگ داشته باشه. چون گفتم که زیاد دیگه وقت و حوصله تست و این حرفا رو نداشتم.
اما روی نسخهء جدید دارم کار میکنم سرفرصت های بیکاری. تاحالا کلی چیز مفید هم بهش اضافه کردم و یکسری باگهایی رو رفع کردم.
سورس نسخه درحال توسعه اینجاست: https://github.com/ferchang/reg8log/tree/dev
دانلودش هم که سمت راست صفحه دکمهء Download ZIP داره.
البته در این سورس ها مقدار بعضی متغییرهای کانفیگ و یکسری مسائل رو برای تست تغییراتی دادم که طبیعتا برای استفادهء عملی باید به مقدارها و وضعیت نرمال تغییر داده بشن.

eshpilen
سه شنبه 17 دی 1392, 08:11 صبح
الان خیلیها میگن داکیومنت نویسی حتی مهمتر از کد خوب هست؟بیجا کردن :لبخند:
گذشته از شوخی خب فکر میکنم این حرف حداقل یخورده اغراق آمیز باشه.
ولی بستگی به کاربرد و شرایط برنامه هم داره خب.
مثلا برنامه ای که تیم روش کار میکنن یا قراره بعدا کس یا کسان دیگری بخوان روش کار کنن، خب فکر میکنم نیازش به داکیومنت نویسی خیلی بیشتر و درواقع اساسیه.
ولی مثلا برنامه من واسه خودمه و من فقط میخوام کارش رو درست انجام بده. هرچند حتی خودم هم تا یک حد حداقلی به داکیومنت/کامنت احتیاج دارم تا اگر بعد از مدت نسبتا طولانی خواستم برگردم سرش، بتونم سریع و راحت و مطمئن تر طرز کار و داستانش رو بفهمم و به یاد بیارم.

eshpilen
سه شنبه 01 بهمن 1392, 08:17 صبح
وای دیگه خسته شدم از بس چیز اضافه کردم و تست کردم.

ولی اون نسخهء قبلی زیاد خوب نبود! این یکی خیلی بهتره!!

نسخهء 2.3 که الان ارائه میشود بهبودها و افزایش امکانات و رفع چندین باگ رو داره.

- الان دیگه تغییر ایمیل هم مثل موقع ثبت نام میتونه نیاز به تایید صحت ایمیل داشته باشه (با ارسال لینک فعال سازی به ایمیل مورد نظر)
این گزینه هم باز آخر کانفیگ و انعطاف رو داره. میشه تعیین کرد که تغییر ایمیل نیاز به تایید صحت ایمیل داشته باشه، نداشته باشه، یا از همون حالتی که برای ثبت نام وجود داره (متغییر کانفیگ email_verification_needed در فایل config_register.php) پیروی کنه. ضمنا تنظیم جداگانه برای ادمین و کاربران عادی وجود داره. پیشفرض رو روی این گذاشتم که برای اکانتهای معمولی از تنظیم email_verification_needed پیروی بشه (که اونم بطور پیشفرض خاموشه)، و برای تغییر ایمیل اکانت ادمین نیازی به تایید صحت ایمیل نباشه.

- در این نسخه تنظیمات جداگانه برای تغییر خودکار کلید لاگین ادمین و کاربران عادی وجود داره. اینم باز امکان آخر کانفیگ پذیری و تطبیق با سناریوهای بیشتری رو میده. مثلا ممکنه بعلت کاهش بار روی دیتابیس و سرور بخوایم تغییر خودکار کلید لاگین رو برای کاربران عادی خاموش کنیم اما برای ادمین روشن باشه (بخاطر مسائل امنیتی)؛ البته تنها دلیلش این نیست؛ یک دلیل دیگه میتونه این باشه که میخوایم اجازه بدیم کاربران بتونن همزمان از چند سیستم لاگین باشن؛ هرچند از نظر امنیتی بهتره اینطور نباشه.

- الان میشه تعیین کرد که برای انجام عملیات ادمینی مثل حذف یا تایید کردن اکانتهای کاربران، نیاز به ورود پسورد ادمین باشه. این کار با متغییر کانفیگ admin_operations_require_password در فایل config_admin.php انجام میشه. مقدارش اگر 0 باشه یعنی نیازی به ورود پسورد نیست، اگر 1 باشه یعنی نیاز هست، اگر عددی بزرگتر از 1 باشه بدین معناست که نیاز به ورود پسورد هست اما هر بار که ادمین پسورد رو وارد میکنه بعد تا اون مدت زمان بر حسب ثانیه دیگه نیازی به ورود مجدد پسورد نداره؛ البته برای این یک چک باکس در اون قسمت ورود پسورد میاد که ادمین اگر خودش انتخابش کنه باعث میشه که در دفهء بعدی تا اون زمان خاص نیازی به ورود مجدد پسورد نباشه.

- چندتا باگ و اینا هم فیکس شد!

eshpilen
سه شنبه 01 بهمن 1392, 11:16 صبح
لامصب یه پروژه ببین چقدر گسترده و پیچیدس چقدر زمان میبره چقدر امکانات چقدر نکته داره چقدر ... .
نمیدونم یک سال چقدره همش اوقات فراغتم رو روی این پروژه علاف بودم. البته عوضش یک چیز خوبی شده که تقریبا هرچی امکانات و انعطاف و تمهیدات امنیتی بنظر خودم یا دیگران رسیده تاحالا توش گذاشتم. تمرین خوبی بود. با این حال هنوزم نمیشه گفت که اونقدری که باید و میتونه کامله. یکسری موارد کمبود هم به مسائل مهندسی نرم افزار مثل شیء گرا کردن و طوری درآوردن که دیگران هم بتونن راحت در برنامه های خودشون ازش استفاده کنن و اینها مربوط میشه. بعضی امکانات هم هست که فعلا بیخیال شدم. ولی نمیدونم شاید دوباره وقت کردم و حال و حوصله داشتم روش کار کردم. ولی فکر میکنم زیاد هم مهم نیست فعلا و ارزشش رو نداره.
یکی از این امکانات که میگم اینه که این سیستم طوری طراحی نشده که امکان لاگین بودن همزمان از چند جا رو بده (مثلا همزمان از روی چند PC و گوشی و غیره). هرچند همین الان هم میشه طوری کانفیگش کرد که این اجازه رو بده، ولی درمقابل تمهیدات و مزایای امنیتیش به این شکل به میزان قابل توجهی تضعیف میشه. مثلا اگر کلید لاگین خودکار موقع لاگین یا لاگ آوت یا، بسته به کانفیگ، در هر درخواست، تغییر نکنه، اونوقت میشه همزمان از روی هر چندتا سیستم لاگین بود، ولی امنیت پایین میاد درمقابل و مثلا اگر اطلاعات کوکی احراز هویت توسط یک هکر سرقت بشه اونوقت میتونه با خیال راحت و بدون محدودیت ازش استفاده کنه (مگر اینکه کاربر خودش کلید لاگین رو با امکانی که برای این مسئله در سیستم گذاشتم Regenerate کنه که اونوقت بقیهء سیستمها همه از لاگین خارج میشن و اطلاعات دست هکر هم بی استفاده میشه). البته خوبیش اینه که حداقل تنظیمات ادمین در این زمینه از کاربران عادی جداست و میتونیم مثلا برای ادمین تعیین کنیم که کلید لاگین بصورت خودکار عوض بشه، ولی برای کاربران معمولی اینطور نباشه؛ البته این بازم بنظر من چندان خوشایند نیست و مسئله رو بقدر کافی توجیه نمیکنه.
بهرحال من فکر میکنم درحال حاضر این مسئلهء امکان لاگین همزمان از روی چند سیستم چندان هم مهم نیست و اولویت نداره. بهرحال هم این امکان هرکاری هم که بکنی امنیت رو تاحدی پایین میاره؛ یعنی خود لاگین موندن در چند جا، برای امنیت چیز جالبی نیست (ولی میشه تاحدی بهترش کرد اگر سیستم رو از ابتدا برای ساپورت این حالت طراحی کنیم).

در فکرم برم روی یه پروژهء دیگه کار کنم و یه برنامهء دیگری که بعدا ممکنه به درد خودم بخوره. شاید اصلا یه برنامهء دسکتاپ یا ترکیبی.
شاید هم بهتر باشه روی همون وب کار کنم که احتمالا بعدا بشه باهاش یه نونی هم دربیاریم :متفکر:

freeman99
یک شنبه 10 اسفند 1393, 13:26 عصر
eshpilen این سیستم رجیستر و لاگینت به درد عمت میخوره بی سواد دست و پا چلفتی این جفنگ چیه درست کردی فکر میکنی خیلی بارته؟ :قهقهه:
پسره چلمنگ :متفکر:
آفرین خوب شد این دلقک رو از این فروم اخراج کردید :لبخندساده:

...

نترسید، گفتم یخورده به خودم توهین کنم ببینم چی میشه :لبخند:

جون تو من الان گفتم سری به گیت هاب بزنم ببینم چه خبر، دیدم یه چند نفری (https://github.com/ferchang/reg8log/network/members) پروژم رو fork کردن.
حالا دقیق نمیدونم واسه چی، چون ظاهرا بهش دست نزدن، و از اونور هم فکر نمیکنم کسی جز خودم بتونه از کدهاش سردربیاره!!
واقعا هم کار کردن روش بخصوص برای دیگران سخته چون ساختار منظمی نداره و شیء گرایی و MVC و این حرفا نداره. بخاطر همین دلم میسوزه اینایی که fork کردن ناکام و دلسرد میشن بیچاره ها!
زیاد فک میکنم که این پروژه رو دوباره دست بگیرم و روش کار کنم کاملتر و اصولی ترش کنم. مثلا شیء گرایی بهتر، یکسری بهبودها که بنظرم میرسه، یجوری که راحتتر بشه با برنامه های دیگران Integrate اش کرد. این چیزا رو که میبینم احساس میکنم یه کار ناقص ارائه دادم که ملت رو سر کار میذاره و ناکام میکنه :ناراحت:
چکار کنم چکار نکنم، همش توی فکر میرم. اصلا خیلی وقته فکر میکنم یه برنامه جالب و مفیدی درست کنم، ایده و انگیزه و هدف قانع کننده براش میخوام، ولی هیچی بنظرم نمیرسه، یعنی هرچی بنظرم میرسه میگم آخه که چی بشه یا نمونش هست یا اونقدر که باید مفید و کاربردی نیست ارزش صرف این همه وقت و انرژی رو نداره میتونم بجاش برم یه مطلب جدید یاد بگیرم یا کار دیگه بکنم یا اینکه بازم صبر کنم یه چیزی که از همه چیز بهینه تر باشه و بازدهی عملی بیشتری داشته باشه پیدا کنم. من آدمی هستم که برای هرکاری نیاز به انگیزه قوی و دلایل محکمی دارم. مثلا از اینکه یه چیزی فقط یا بیشتر نمایشی درست کنم یا یه چیزی که نمونه بازمتنش از قبل هست، اصلا بدم میاد و دست و دلم طرفش نمیره. فکر کنم چون شغلم برنامه نویسی نیست و از این راه امرار معاش نمیکنم در نتیجه همینطوری انگیزه ندارم کاری بکنم، فقط منتظرم یه موارد موردی پیش بیاد و مسئله رو، معمولا با برنامه های کوچک و نسبتا ساده ولی خلاق و جالب، حل کنم. خصوصا علاقه دارم کار چند حیطه ای باشه که بتونم از دانش چند حیطه ای و فناوری های متنوع همزمان استفاده و ترکیب کنم. اینکه مثلا روی یک برنامهء خاص فقط در یک زبان و حیطه زیاد کار کنم برام جذاب نیست چون خودم که نیاز ندارم و چیز خاصی هم نیست احساس میکنم چیز جدید و جالب آنچنان بدردبخوری ازش یاد نمیگیرم. اصلا بد عادت شدم که همش میخوام جالب و سرگرم کننده باشه و خط به خط چیزهای جدید و ابتکار توش باشه. ولی الان دیگه مدتیه زیاد بیکار شدم. آخرین چیزی که یاد گرفتم برنامه نویسی اندروید بود که حتی برای اونم هرچی فکر کردم برنامه و تمرین درست و حسابی برای انجام دادن به ذهنم نرسید! یعنی چندتا مورد به ذهنم رسید، ولی دیدم آخرش که چی به چه دردی میخوره زیادم مفید و لازم نیست!! دیگه همین مونده برم مدتی دیگه هم مثلا زبان جاوا رو یاد بگیرم :لبخند: بعد اون تموم بشه اونوقت دوباره بیکار میشم. این همه بلدم ولی نمیدونم ازشون چه استفاده عملی بکنم!
حالا شاید همین سیستم رجیستر لاگین بد چیزی نباشه. نمونش در این حد عملا نیست و اگر یه چیز کامل و استانداردی بشه میتونه جزو برنامه های بازمتنی بشه که در سراسر دنیا استفاده کنن. فقط اگر میتونستم هرچی زودتر درستش کنم بهتر میشد، چون میترسم یکی بالاخره جای این بیاد و این پروژه و فرصت هم از بین بره! لامصب این زمان و اتلاف وقت ها حوصله آدم رو سر میبره و خسته و ناامید میکنه. واسه همین دوست دارم خیلی سریع طراحی کنم و کد بزنم، با سرعت موشک، با قدرت بولدوزر!! یکی از دلایلی که در این پروژه فقط با سرعت و عجله ولو بدون شیء گرایی و نظم و اصول مهندسی نرم افزار کد زدم همین بود که میخواستم هرچه زودتر به کار بیفته! البته شاید بد هم نشد، چون الان یه دید و تسلط خوبی نسبت بهش دارم و فکر میکنم سریعتر و راحتتر میتونم اصلاح و بازنویسیش کنم. اون چیزی که درست کردم بنظرم یجور prototype شده! واسه کارهای اول این روش prototype کردن و نمونه های آزمایشی و محک درست کردن شاید خوب هم باشه. منکه اینطور فکر کردم! از اول اگر میخواستم روی جنبه های دیگش هم تمرکز کنم در جزییات و پیچیدگی و سوالات و آیتم های لیست todo غرق میشدم، چون همینطوریش بحث الگوریتم ها و امنیت و امکاناتش واقعا گسترده و پیچیده بود و نمیشد با این وزن های افزوده از پسش براومد!
این پروژه خصوصیات واقعا خوبی داره. یکیش و شاید اول اینکه برای خودم هم میتونه 100% خیلی مفید و کاربردی باشه چون در بیشتر برنامه ها و سایتهای وب و اینها به یک سیستم رجیستر و لاگین نیازه، و سیستم رجیستر و لاگین حرفه ای بازمتن و با امکانات و انعطاف زیاد و امنیت بالا عملا وجود نداره. یکی دیگه اینکه یه چیزی هست که درست و حسابی درستش کنی در کل دنیا هم خیلی ها مشتریش میشن و هم اعتبار میاره و هم کار مفیده و کارمای مثبت زیادی تولید میکنه (البته این کارما و اینا فرضیه و تئوری هستش، ولی فکر میکنم درست باشه :لبخند:)، بعد یه خوبی دیگش اینه که با فناوریهای و مباحث کم و بیش متنوعی هم درگیره: جاوااسکریپت، جی کوئری، HTML، PHP، MySQL، امنیت و رمزنگاری پیشرفته، ... یجورایی حس تنوع طلبی و چند حیطه ای گرایی منو تاحدی ارضا میکنه. ولی مثلا خیلی برنامه های دیگه بخصوص غیروب اینطور نیستن. مثلا برم روی موبایل هرچقدر هم که پشتک بالانس بزنم معمولا برنامه های کمی هست که این همه جنبه و حیطه و مباحث پیشرفته و جالب داشته باشه.

freeman99
سه شنبه 12 اسفند 1393, 20:22 عصر
خب دارم یک لیست todo درست میکنم. اول موارد مهمتر و ضروری تر که در کارکرد برنامه موثر هستن.

- میخوام از Class autolaoding استفاده کنم و دیگه مدام require_once و اینا بکار نبرم. اینطوری برنامه کم حجم تر و ساده تر و مطمئن تر میشه. اصلا من نمیدونم چرا وقتی میشه کلاسها رو بطور خودکار Load کرد باید از اینکلود دستی استفاده کنیم! کسی میدونه؟
یکی از اصولی که تاحالا در منابع دیدم اینه که هرچی انجام کارها رو به خود کامپیوتر بسپارید بهتره، هرچند طبیعتا هزینه داره و مقداری (خوشبختانه معمولا قابل توجه نیست) از پرفورمنس و منابع سخت افزار رو مصرف کنه.

- باید یه فکری برای متغییرهای سشن برنامه هم بکنم که از متغییرهای سشن بقیهء برنامه ها جدا بشن (این در زیرسیستم رمزنگاری سشن هم یک مشکل حل نشده بود). مثلا میتونیم همهء متغییرهای سشن خودم رو داخل یک آرایه ببرم به این صورت مثلا: ‎$_SESSION['reg8log']['some_var_name']‎
البته میشه هم به ابتدای تمام متغییرهام پیشوند reg8log رو اضافه کنم.

- توکن امنیتی (antixsrf_token) رو بجای کوکی در سشن ذخیره کنم چون استفاده از کوکی یک ضعف امنیتی خاصی داره (مربوط به سابدامین های مستقل).

- احتمالا توابع mysql_‎ رو که deprecate شدن بیام و با مثلا PDO عوض کنم. البته این گزینه در نظر من ضرورت حاد نداره و اگر وقت کردم و صرف میکرد انجام میدم، چون باوجودی که این توابع deprecate شدن ولی بعید میدونم به این زودیها کلا حذف بشن (اصولش از منم بپرسید میگم درست نیست به این زودیها حذفش کنن). فقط باید به فکر باشم اون Warning و این حرفا رو که احتمالا در نسخه های جدید PHP در این مورد میده خفه کنم!

دیگه؟ :متفکر:

آهان راستی قصد ندارم از MVC استفاده کنم. چون فعلا بهش احساس نیاز مبرمی نمیکنم و بنظرم موارد کاربردی تر و مهمتری و ضروری تری فعلا وجود دارن که بتونم همهء اونا رو انجام بدم کلی کار کردم. ولی احتمالا از شیء گرایی در برنامه بیشتر استفاده کنم و یکسری کدها و عملیات رو که توی کد همینطوری ولو هستن توی کلاسهایی (یا شاید هم در بعضی موارد صرفا توابع جدید) پکیج کنم.

freeman99
پنج شنبه 06 فروردین 1394, 12:21 عصر
خب فعلا یه کارهای قابل توجهی رو روی این پروژه انجام دادم. البته هنوز کل پروژه رو تست گسترده مجدد نکردم و به همین دلیل راحت ممکنه باگ ماگ زیاد داشته باشه. فعلا در انشعاب dev هست طبیعتا و هنوزم دارم روش کار میکنم: https://github.com/ferchang/reg8log/tree/dev

بهبودهایی که تا اینجا اعمال کردم:

- class autoloading

- function autoloading

- کلاس لودر و دسترسی به متغییرهای کانفیگ که دسترسی به متغییرهای کانفیگ در بیشتر برنامه دیگه از طریق این کلاس انجام میشه و اینطوری هم کد خواناتر میشه و از اشتباه گرفتن متغییرهای کانفیگ با متغییرهای دیگر هم جلوگیری میشه و هم از یکسری مسائل دیگر مثل اینکلود نشدن و تعریف نشده بودن کانفیگ های مورد نظر جلوگیری میشه و از طرف دیگر تعداد قابل توجهی دستورهای اینکلود فایلهای کانفیگ مختلف در جاهای مختلف از برنامه حذف شدن. این مزایایی که گفتم البته درمورد دو آیتم قبلی (class autoloading و function autoloading) هم صدق میکنن.

- تمام متغییرهای سشن برنامه به درون آرایهء reg8log در سشن منتقل شدن تا از تداخل با متغییرهای دیگر سشن که توسط برنامه ها و کاربران احتمالی دیگر ست شدن جلوگیری بشه. بخصوص این از جهت موقعی که سیستم رمزنگاری سشن برنامه فعال هست خیلی مهم بود چون میزد همه متغییرهای سشن دیگر رو حذف میکرد.

- توکن امنیتی ضد CSRF رو به درون سشن بردم (قبلا در کوکی ذخیره میشد که در ارتباط با سابدامین ها ضعف امنیتی داشت)

- الگوریتم هش پسورد رو به bcrypt که خودم همش توصیه میکردم تغییر دادم (قبلا استفاده نکرده بودم چون روی یک هاست دیدم ساپورت نبود چشمم ترسید!)

- سیستم error logging پیاده کردم که تمام خطاها و پیامهای PHP رو لاگ کنه. در این جریان متوجه شدم که این سیستم برای زمان توسعه و تست هم میتونه واقعا مفید باشه چون گهگاه یکسری پیامهای PHP به عللی در مرورگر دیده نمیشن و آدم متوجهشون نمیشه.

- بهبودهای استاندارد و سازگاری در سطح کدنویسی هم که متعدد بوده دیگه ریز نمیشم و توضیح زیاد نمیخواد. مثلا موارد که از متغییر استفاده کرده بودم ولی استفاده از ثابت خیلی مناسب تر و استانداردتر بوده اصلاح کردم.

- استفاده از کیورد global رو با استفاده از آرایهء ‎$GLOBALS در تقریبا تمامی موارد عوض کردم، چون اینطوری کد خوانایی بیشتری پیدا میکنه و از اشتباه گرفتن متغییرهای محلی با متغییرهای سراسری هم جلوگیری میشه.

- یکسری جاهایی از @ برای جلوگیری از تولید پیامهای خطا استفاده کرده بودم، چند مورد رو که بنظرم ضروری نبود و میتونست باعث غفلت از یکسری باگها بشه حذف کردم تا برنامه هر خطایی مشکلی چیزی داره آدم متوجه بشه. هرچند هنوز تعدادی از کاربرد @ در جاهای دیگر برنامه هست ولی اونا اینقدر اهمیت نداشتن و حذفشون هم اینقدر ساده نبود بنظرم.

چیزهایی که توی لیست هست انجام بدم یا باید روی تصمیم برای انجام دادنشون تصمیم بگیرم:

- تغییر تمام یا مواردی از == ها به === که میشه، برای جلوگیری از باگها و حفره هایی که میتونه بر اثر رفتارهای غیرمنتظره عملگر == در PHP پیش بیاد.

- cache friendly تر کردن برنامه (در حال حاضر همه صفحات با هدرهای ضدکش ارسال میشن - این موقع توسعه و تست کمک بزرگی میکنه ولی در مواقع استفاده عادی فکر نمیکنم مناسب باشه).

- درمورد حذف تمام موارد کاربرد الگوریتم های قدیمی و منسوخ و ناامن md5 و sha1 در برنامه و جایگزینی اونا با آلترناتیوهای امن تر فکر کردم و حتی پرسیدم (http://crypto.stackexchange.com/questions/24596/should-i-remove-these-use-cases-of-md5-sha1-from-my-program) و تحقیق کردم ولی هنوز به نتیجه قطعی نرسیدم که آیا این کار واقعا لازمه یا نه. من از این الگوریتم ها در کاربردها و به شکل های خاصی استفاده کردم که تاجاییکه میدونم از نظر امنیتی مشکلی ایجاد نمیکنن، ولی جای شک و دلایل دیگر هنوز باقیست و اذیت میکنه!