16

TL;DR Durandal Single Page Application (SPA) で特定のページを表示するためにユーザーにログインを求める適切なパターンは何ですか?

ユーザーがログインを必要とする「ページ」に移動しようとすると、代わりにログインページにリダイレクトされるシステムが必要です。このログイン ページで認証に成功したら、ログイン ページにリダイレクトされる前に、以前にアクセスを試みたページにアプリケーションをリダイレクトさせたいと思います。

ログインページとの間でユーザーをリダイレクトするために実装できると考えられる1つの方法は、認証が必要なページへの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();
} 

制限事項

この方法の 1 つの制限は、ユーザーが認証されてログイン ページからリダイレクトされた後、ログイン ページに進むことができることです。

さらに、

router.navigate(instruction.fragment + 'LoginRedirect', false);

LoginRedirectURL にフラッシュアップが表示されることがあります。

より深刻な制限は、ユーザーがログイン ページを押しても前の (保護されていない) ページに移動しないことです (代わりに、ログイン ページにリダイレクトされる保護されたページに移動します)。

またguardRoute、ページを更新する際にバグがあるようです (こちらを参照してください。これはまだ問題ですか?

上記の動作をカプセル化し、上記と同様の制限を持たない標準的なデュランダル パターンはありますか?

4

2 に答える 2