TL; DR Что такое хороший шаблон, требующий от пользователя входа в систему для просмотра определенных страниц в приложении Durandal Single Page Application (SPA)?
Мне нужна система, в которой, если пользователь пытается перейти на "страницу", которая требует, чтобы они вошли в систему, они вместо этого перенаправляются на страницу входа. После успешной аутентификации на этой странице входа мне хотелось бы, чтобы приложение перенаправляло их на страницу, к которой они ранее пытались получить доступ, прежде чем они были перенаправлены на страницу входа.
Один метод, который я могу представить, который может быть реализован для перенаправления пользователя на страницу входа и из нее, - это сохранить URL-адрес страницы, которая требует аутентификации в истории браузера, и после успешной проверки подлинности вернитесь к этой истории на странице входа.
Реализация
Я попытался реализовать описанный выше шаблон, но с ним несколько проблем. В main.js
(или где-либо перед тем, как router.activate()
вызывается) я защищаю маршрут, требующий проверки подлинности:
router.guardRoute = function (instance, instruction) {
if (user.isAuthenticated()) {
return true;
} else {
if (instance && typeof (instance.allowAnonymous) === "boolean") {
if (!instance.allowAnonymous) {
/* Use one of the following two methods to store an item in the
browser history. */
/* Add guarded URL to the history and redirect to login page.
* We will navigate back to this URL after a successful login.
*/
if (history.pushState) {
history.pushState(null, null, '#' + instruction.fragment);
}
else {
location.hash = '#' + instruction.fragment;
}
*/
/* This will not work - history is not updated if the fragment
* matches the current fragment.*/
////router.navigate(instruction.fragment, false);
/* The following solution puts in a fragment to the history
* that we do not want the user to see. Is this an
* acceptable solution? */
router.navigate(instruction.fragment + 'LoginRedirect', false);
return router.convertRouteToHash("login");
}
}
return true;
}
};
В shell.js
я добавляю маршрут на страницу входа:
return {
router: router,
activate: function () {
router.map([
...
{ route: 'login', title: '', moduleId: 'viewmodels/login', nav: true },
...
]).buildNavigationModel();
return router.activate();
},
...
}
В viewmodels/login.js
Затем у меня есть фрагмент кода:
if (account.isAuthenticated()) {
router.navigateBack();
}
Ограничения
Одно из ограничений этого метода заключается в том, что он позволяет пользователю перейти на страницу входа в систему после того, как они прошли аутентификацию и перенаправлены с страницы входа.
Кроме того, используя
router.navigate(instruction.fragment + 'LoginRedirect', false);
Я иногда вижу, как LoginRedirect
вспыхивает в URL-адресе.
Более серьезным ограничением является то, что пользователь, возвращающийся на страницу входа, не будет перенесен на предыдущую (не охраняемую) страницу (но вместо этого будет отправлен на охраняемую страницу, которая будет перенаправляться на страницу входа).
Также кажется, что есть ошибка с обновленной страницей guardRoute
, позволяющей обновить страницу (см. здесь. Это еще проблема?
Являются ли они стандартными шаблонами Дюрандала, которые инкапсулируют вышеуказанное поведение и не имеют аналогичных ограничений, перечисленных выше?