Как лучше при логине или регистрации правильно вернуться назад, чтобы не уйти со своего сайта?
По вводным: проект на Next.js app v14.
Каким способом определить предыдущий адрес страницы, чтобы вернуться назад, если это - страница моего сайта, или перейти на главную, если предыдущая страница - чужая (например, пользователь сразу ввел в поиске www.my-site/login)?
По вводным: 1) document.referrer остается пустым при переходе с чужой страницы на мой сайт и при переходе по страницам сайта.
По вводным: document.referrer.includes(window.location.origin) - всегда false, т.к. document.referrer пустой.
"use client"; import { usePathname } from 'next/navigation'; import { useEffect} from 'react'; export default function IsExternal() { const pathname = usePathname(); useEffect(() => { console.log("document.referrer", document.referrer); // всегда пустой const cameFromExternalSite = !document.referrer.includes(window.location.origin); // всегда true if(cameFromExternalSite){ sessionStorage.setItem("prevPath", "external" ); } console.log("Внешний переход:", cameFromExternalSite); // всегда true }, [pathname]); return null; }
Сейчас ситуация такая: 2) проверяла sessionStorage, но не смогла получить предыдущую страницу
"use client"; import { usePathname, useSearchParams } from 'next/navigation'; import { useEffect, useRef } from 'react'; export default function TrackPreviousPage() { const pathname = usePathname(); const prevPath = useRef(null); const previousPage = document.referrer; const currentOrigin = window.location.origin; useEffect(() => { if (prevPath.current) { sessionStorage.setItem("prevPath", prevPath.current); // записывает текущий адрес, а не предыдущий } prevPath.current = pathname; }, [pathname]) return null };
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
В Next.js App Router лучше не полагаться только на
document.referrer. Referrer может быть пустым, обрезанным политикой браузера или чужим сайтом. Надёжнее передавать свой безопасныйreturnToпараметр при переходе на login/register и обязательно валидировать его перед редиректом.Например, когда пользователь пытается открыть защищённую страницу, редиректите его так:
const returnTo = encodeURIComponent('/profile/settings'); redirect('/login?returnTo=' + returnTo);const returnTo = encodeURIComponent('/profile/settings'); redirect('/login?returnTo=' + returnTo);
После логина проверяйте, что returnTo — это внутренний путь, а не внешний URL:
function safeReturnTo(value) { if (!value || typeof value !== 'string') return '/'; if (!value.startsWith('/')) return '/'; if (value.startsWith('//')) return '/'; return value; }function safeReturnTo(value) { if (!value || typeof value !== 'string') return '/'; if (!value.startsWith('/')) return '/'; if (value.startsWith('//')) return '/'; return value; }
Если пользователь сам ввёл
/loginв адресной строке,returnToне будет, и вы отправите его на главную или в личный кабинет.Для client component можно использовать
router.back(), но только если вы уверены, что предыдущая страница была внутри сайта. Иначе пользователь может уйти обратно в поиск/чужой сайт. Поэтому для auth flow лучше не back, а явный returnTo.Если всё же хотите использовать referrer, проверяйте origin:
const ref = document.referrer; const url = ref ? new URL(ref) : null; const sameSite = url && url.origin === window.location.origin;
Но referrer — запасной вариант, не основной.
Итог: используйте параметр
returnTo, храните только относительный путь, отсекайте внешние URL и при отсутствии значения отправляйте на главную/кабинет. Это безопаснее и предсказуемее, чемdocument.referrerили слепойrouter.back().