یک دموی عملی از مهاجرت بدون داونتایم با استفاده از Password Hashing 🔐
نیازهای امنیتی به مرور زمان تغییر میکنند. چیزی که پنج سال پیش «به اندازهی کافی امن» محسوب میشد، ممکن است امروز حتی از یک ممیزی امنیتی هم رد نشود. ⚠️
شما باید به یک الگوریتم مدرن مثل Argon2 یا Bcrypt مهاجرت کنید.
اما اینجا یک مشکل اساسی وجود دارد: هش کردن یک عملیات یکطرفه است. شما نمیتوانید هشهای قبلی را برعکس کنید تا آنها را «ارتقا» دهید. 🔁❌
اگر به سادگی پیادهسازی IPasswordHasher را عوض کنید، برنامه را میشکنید.
تمام کاربران فعلی که تلاش میکنند لاگین کنند با خطا مواجه میشوند، چون hasher جدید فرمت قدیمی را نمیفهمد. 🚫
در این مقاله میخواهم مفهوم zero-downtime migration را به صورت عملی نشان بدهم. 🛠
سیستمهای واقعی محدودیتهای بیشتری دارند (و شما نباید سیستم احراز هویت را از صفر خودتان بنویسید).
اما این یک مثال تمیز از یک الگو است که میتوانید برای مهاجرت دیتابیس دوباره استفاده کنید:
• مهاجرت از فرمت قدیمی به فرمت جدید
• حفظ رفتار قبلی سیستم
• مهاجرت تدریجی دادهها
• حذف legacy فقط وقتی کار تمام شد
بیایید شروع کنیم. 🚀
The Naive Approach and Why It Fails
رویکرد سادهلوحانه و اینکه چرا شکست میخورد ❌
فرض کنید یک سیستم احراز هویت ساده دارید.
میخواهید hasher قدیمی PBKDF2 را با یک پیادهسازی استاندارد Argon2 جایگزین کنید.
ممکن است فکر کنید:
«فقط پیادهسازی جدید را در dependency injection ثبت میکنم.»
// Switching from LegacyHasher to ModernHasher
builder.Services.AddSingleton<IPasswordHasher, ModernHasher>();
سناریوی شکست این است:
🔸️کاربران جدید:
ثبتنام میکنند و بدون مشکل لاگین میشوند. پسورد آنها از روز اول با Argon2 هش شده است. ✅
🔸️کاربران قدیمی:
کاربر پسورد درست را وارد میکند. سیستم هش قدیمی PBKDF2 را از دیتابیس میگیرد. 📦
🔸️فاجعه:
ءModernHasher تلاش میکند هش PBKDF2 را verify کند. فوراً fail میشود و 401 Unauthorized برمیگرداند. 💥
شما ناخواسته کل کاربران فعلی سیستم را لاک کردهاید.
ما به راهی نیاز داریم که هر دو الگوریتم همزمان پشتیبانی شوند، بدون اینکه کد لاگین به یک آشغال غیرقابل نگهداری تبدیل شود. 🧨
The Solution: Migration on Login
راهحل: مهاجرت در زمان لاگین 🔄
استراتژی ساده است:
ما دیتابیس را با یک batch job مهاجرت نمیدهیم.
ما کاربران را lazy و زمانی که هویت خودشان را ثابت میکنند مهاجرت میدهیم.
جریان کار به این شکل است:
Attempt 1:
تلاش کن پسورد را با الگوریتم جدید verify کنی. 🥇
Attempt 2 (Fallback):
اگر شکست خورد، بررسی کن ببین الگوریتم قدیمی میتواند آن را verify کند یا نه. 🥈
The Migration:
اگر verification با الگوریتم قدیمی موفق بود:
• کاربر را لاگین کن (موفقیت) ✅
• بلافاصله پسورد را با الگوریتم جدید دوباره هش کن 🔐
• رکورد دیتابیس را آپدیت کن 🗄
از این به بعد، لاگینهای بعدی این کاربر از مسیر استاندارد جدید عبور میکنند. 🎯