Durandal login page redirect pattern

后端 未结 2 2194
野性不改
野性不改 2021-02-01 07:58

TL;DR What is a good pattern for requiring a user to login in order to view certain pages in a Durandal Single Page Application (SPA)?

I need a system w

相关标签:
2条回答
  • 2021-02-01 08:09

    My method:

    I've developed a view model base function, which is base for all view models of my application. In the canActivate method (in view model base), I'll return false and navigate to login page if the current user does not have permission to view that page. I also perform a query against a client side database (to determinate user has access to page or not).

    The good news is that Durandal supports deferred execution for canActivate. In the login page, after a successful login, I'll use navigator.goBack(); to return to previous page.

    I hope this helps you.

    0 讨论(0)
  • 2021-02-01 08:11

    Query-string pattern

    Attempting to implement the "navigate back" method described in my question I have decided against using this method because of the limitations I have described above.

    I have found in practice that a method which works much better is to pass the URL to the page which requires authentication as a query string to the login page, which can then use this to navigate forward to this URL once a user is authenticated.

    Below is an outline of an implementation of this method which I have adopted. I am still keen to learn about any other login patterns that people have adopted for use in Durandal applications however.

    Implementation

    In main.js (or anywhere before router.activate() is called) I still guard the route which requires authentication:

    router.guardRoute = function (instance, instruction) {
        if (user.isAuthenticated()) {
            return true;
        } else {
            if (instance && typeof (instance.preventAnonymous) === "boolean") {
                if (instance.preventAnonymous) {
                    return 'login/' + instruction.fragment;
                }
            }
    
            return true;
        }
    };
    

    In shell.js:

    return {
        router: router,
        activate: function () {
            router.map([
                ...
                { route: 'login', title: '', moduleId: 'viewmodels/login', nav: true },
                { route: 'login/:redirect', title: '', moduleId: 'viewmodels/login', nav: true },
                ...
            ]).buildNavigationModel();
            return router.activate();
        },
        ...
    }
    

    In viewmodels/login.js:

    viewmodel = {
        ...,
        canActivate: function() {
            if (!user.isAuthenticated()) {
                return true;
            }
            return false;
        },
    
        activate: function(redirect) {
            viewmodel.redirect = redirect || "";
        },
        loginUser() {
            ...
            if (user.isAuthenticated()) {
                router.navigate(viewmodel.redirect);
            }
            ...
        },
        ...
    }
    

    Limitation

    One minor negative of this method is the prescense of the page fragment to redirect to upon a succesful login in the application URL query string. If you do not like the prescence of this page fragment in the URL query string, local storage could easily be used instead to store this value. In router.guardRoute one could simple replace the line

    return 'login/' + instruction.fragment;
    

    with

    /* Check for local storage, cf. http://diveintohtml5.info/storage.html */
    if ('localStorage' in window && window['localStorage'] !== null){
        localStorage.setItem("redirect", instruction.fragment);
        return 'login/';
    } else {
        return 'login/' + instruction.fragment;
    }
    

    and our activate method could look like:

    activate: function(redirect) {
        if ('localStorage' in window && window['localStorage'] !== null){
            viewmodel.redirect = localStorage.getItem("redirect");
        } else {
            viewmodel.redirect = redirect || "";
        }
    },
    
    0 讨论(0)
提交回复
热议问题