6.3 KiB
بازگشت به صفحهٔ مبدأ بعد از لاگین (redirect-back)
پروژه
nobat724_front (سایت عمومی)
زمینه
مکانیزم بازگشت بعد از لاگین از قبل وجود دارد: مرحلهٔ تأیید کد (SendReq.js) بعد از ورود موفق، پارامتر ?redirect= را از URL میخواند و کاربر را به همان مسیر برمیگرداند (فقط مسیر داخلی امن). اما لینکها/ناوبریهای لاگین در سایت این پارامتر را نمیسازند — بهجز یک مورد (components/doctor/claim/index.js). نتیجه: کاربر از هر صفحهای (مثلاً صفحهٔ پزشک برای گرفتن نوبت) روی «ورود | ثبت نام» بزند، بعد از لاگین به / (خانه) میرود، نه صفحهٔ مبدأ.
مشکل / هدف
هر جای سایت که به /login میرویم، باید مسیر فعلی را بهصورت ?redirect=<current-path> به لینک لاگین اضافه کنیم تا بعد از ورود موفق کاربر به همان صفحه برگردد. الگوی درست از قبل در پروژه هست و فقط باید به بقیهٔ نقاط تعمیم داده شود.
فایلهای مرتبط
| فایل | نقش |
|---|---|
components/register/verificationPage/SendReq.js |
(بدون تغییر) منطق بازگشت با ?redirect= — L89–95 |
components/doctor/claim/index.js |
(مرجع الگوی درست) L191 — /login?redirect=${encodeURIComponent(pathname)} |
components/layout/header/Content.js |
لینک اصلی «ورود | ثبت نام» هدر — L43 |
app/payment/[uuid]/page.js |
router.push("/login") هنگام نبود auth — L35 |
app/dashboard/page.js |
redirect("/login") سمت سرور برای صفحهٔ محافظتشده — L29 |
app/component/ModalLogout.js |
router.replace("/login") بعد از خروج — L19 (به «نکات» رجوع کن) |
وضعیت فعلی
منطق بازگشت که باید حفظ شود (SendReq.js L89–95):
// بازگشت به صفحهٔ مبدأ اگر ?redirect= داده شده (فقط مسیر داخلی امن)
const redirect = new URLSearchParams(window.location.search).get("redirect");
window.location.href =
redirect && redirect.startsWith("/") && !redirect.startsWith("//")
? redirect
: "/";
الگوی درستِ موجود (components/doctor/claim/index.js L191):
<Link href={`/login?redirect=${encodeURIComponent(pathname)}`} className="w-full">
لینک هدر که پارامتر ندارد (components/layout/header/Content.js L40–47) — این کامپوننت "use client" است و همین حالا const pathname = usePathname(); را دارد (L17):
{isLogged ? (
<ProfileUser />
) : (
<Link href="/login">
<Button variant="outlined" color="primary">
ورود | ثبت نام
</Button>
</Link>
)}
وظایف
۱. لینک لاگین هدر (اصلیترین)
در components/layout/header/Content.js L43، pathname که همینجا موجود است را به لینک اضافه کن. از رفتن به /login?redirect=/login جلوگیری کن:
<Link
href={
pathname && pathname !== "/login"
? `/login?redirect=${encodeURIComponent(pathname)}`
: "/login"
}
>
<Button variant="outlined" color="primary">
ورود | ثبت نام
</Button>
</Link>
۲. ناوبری لاگین صفحهٔ پرداخت
در app/payment/[uuid]/page.js L35 (router.push("/login"))، مسیر فعلی را ضمیمه کن. این کامپوننت client است؛ اگر usePathname وارد نشده، آن را از next/navigation وارد کن و استفاده کن:
import { usePathname } from "next/navigation";
// ...
const pathname = usePathname();
// ...
router.push(`/login?redirect=${encodeURIComponent(pathname)}`);
۳. redirect سمت سرور داشبورد
در app/dashboard/page.js L29، صفحهٔ محافظتشده هنگام نبود auth به لاگین میرود؛ مقصد بازگشت را ثابت /dashboard بگذار:
return redirect("/login?redirect=/dashboard");
(چون این redirect سمت سرور است و به مسیر ثابت داشبورد مربوط است، نیازی به usePathname نیست.)
نکات مهم
- پارامتر در طول جریان لاگین حفظ میشود: صفحهٔ
/login→ContentLogin→RegisterPageمرحلهٔ ارسال کد و تأیید را با state داخلی (isSendMsg) عوض میکند و ناوبری جدید انجام نمیدهد، پس URL روی/login?redirect=...میماند وSendReq.jsباwindow.location.searchآن را میخواند. نیازی به پاسدادن prop اضافه نیست. - امنیت redirect از قبل هندل شده: فقط مسیرِ داخلی که با
/شروع شود و با//شروع نشود پذیرفته میشود (SendReq.jsL92). مقدار را همیشه باencodeURIComponent(pathname)بساز. app/login/page.js: کاربرِ از قبل لاگینشده به/هدایت میشود (ability.can("access","Login")). این رفتار درست است و نباید تغییر کند؛ فقط برای کاربرِ مهمان?redirect=معنا دارد.ModalLogout.js(L19) را تغییر نده: بعد از خروج بردن کاربر به/loginبا?redirect=به صفحهٔ محافظتشده باعث حلقه/بازگشت ناخواسته میشود. لاگاوت باید به/loginسادهٔ فعلی برود.- صفحهٔ appointment inline login دارد: جریان گرفتن نوبت با
setStep(3)بعد از لاگین در همان صفحه میماند (SendReq.jsL86–87) و ناوبری نمیکند؛ نیازی به?redirect=ندارد و نباید دست بخورد. usePathnameفقط در Client Component کار میکند؛ برای redirectهای سمت سرور (وظیفهٔ ۳) از مسیر ثابت استفاده کن.- بعد از تغییر:
npm run buildبدون خطا.