2016-10-05 3 views
2

У нас есть большое приложение для марионеток с дополнительными приложениями/модулями.Аутентифицированные и общедоступные маршруты в македонской магии

Каждый из этих регистров регистрирует свой собственный маршрутизатор в пределах App.addInitializer.

Что такое лучший способ отметить определенные маршруты как общедоступные и другие лица, требующие аутентификации?

У меня есть способ в приложении проверить, является ли пользователь аутентифицированным или нет, но я стараюсь не выполнять эту проверку в каждом обработчике маршрута.

PrivateModuleRouter.Router = Marionette.AppRouter.extend({ 
    appRoutes: { 
    "privateRoute(/)" : "handlePrivateRoute", 
    } 
}); 

var API = { 
    handlePrivateRoute: function() { 

    //I don't want to repeat this everywhere.. 

    if(!Auth.isAuthenticated()) { 
     App.navigate('/login', {trigger:true}); 
    } else { 
     PrivateRouteController.showForm(); 
    } 
}; 

App.addInitializer(function(){ 
    new PrivateModuleRouter.Router({ 
    controller: API 
    }); 
}); 

Есть ли способ в определении маршрута маркирует его как частные, а затем обработчик верхнего уровня маршрута выполняет эту проверку?

Если это на Router событие, хотя, это может не сработать, если обработчик маршрута был вызван непосредственно (не проходя trigger:true и призывая API.handlePrivateRoute() непосредственно

+0

Вы были в состоянии решить проблему?Если ответ вам помог, вы должны принять его или создать свой собственный ответ, если ничего не помогло. –

ответ

0

Отказ от ответственности:., Как я лично не использовать марионетка, это ответ основан только на Backbone.

выполнить функцию

Backbone обеспечивает execute функцию маршрутизатора как способ справиться с такой логикой. даже exampl е имеет логику аутентификации в нем:

var Router = Backbone.Router.extend({ 
    execute: function(callback, args, name) { 
    if (!loggedIn) { 
     goToLogin(); 
     return false; 
    } 
    args.push(parseQueryString(args.pop())); 
    if (callback) callback.apply(this, args); 
    } 
}); 

аутентификация маршрутизатор

Один из способов избежать повторений выполнить в каждом маршрутизаторе будет сделать базовый маршрутизатор для вашего приложения.

var BaseRouter = Backbone.Router.extend({ 
    constructor: function(prefix, opt) { 
     // get the hash 
     this.auth = _.result(this, "auth", {}); 
     BaseRouter.__super__.constructor.apply(this, arguments); 
    }, 

    // requires auth by default? 
    authDefault: false, 

    /** 
    * Check the `auth` hash for a callback. Returns `authDefault` if 
    * the callback is not specified. 
    * @param {String} callbackName name of the function. 
    * @return {Boolean} true if the callback is private. 
    */ 
    hasAuth: function(callbackName) { 
     return _.result(this.auth, callbackName, this.authDefault); 
    }, 

    // To easily override the auth logic in a specific router 
    checkAuth: function(){ 
     return Auth.isAuthenticated(); 
    }, 

    execute: function(callback, args, name) { 
     if (this.hasAuth(name) && !this.checkAuth()) { 
      this.navigate('/login', { trigger: true }); 
      return false; 
     } 
    } 
}); 

Определение конкретных маршрутизаторов

Тогда для каждого вашего маршрутизатора, расширить BaseRouter.

var SpecificRouter = BaseRouter.extend({ 
    routes: { 
     '*otherwise': 'home', // notice the catch all 
     'public': 'publicRoute', 
     'private': 'privateRoute', 
     'unspecified': 'defaultAccessRoute' 
    }, 

    /** 
    * The auth hash works like this: 
    * "functionName": [boolean, true if needs auth] 
    * 
    * home and publicRoute could be left out as it's the default here. 
    */ 
    auth: { 
     home: false, // public 
     publicRoute: false, // public 
     privateRoute: true, // needs authentication 
     // defaultAccessRoute will be public because BaseRouter 
     // defines `authDefault: false`. 
    }, 

    home: function() {}, 
    publicRoute: function() {}, 
    privateRoute: function() {}, 
    defaultAccessRoute: function() {}, 

}); 

И для маршрутизатора, который все маршруты являются частными по умолчанию:

var PrivateRouter = BaseRouter.extend({ 
    authDefault: true, 
    routes: { 
     '*otherwise': 'home', // private 
     'only-private': 'onlyPrivate', // private 
    }, 

    // ...snip... 

    /** 
    * Optional example on how to override the default auth behavior. 
    */ 
    checkAuth: function() { 
     var defaultAuthResult = PrivateRouter.__super__.checkAuth.call(this); 
     return this.specificProperty && defaultAuthResult; 
    } 

}); 
0

В GitHub вы можете найти много решения для вызова некоторых методов перед выполнением маршрутизатора. Для marionette вы можете использовать идеи от marionette-lite расширение, основанное в системе фильтров.

Вы должны определить фильтр, например RequresAuthFilter как:

import { Filter } from 'marionette-lite'; 

const RequresAuthFilter = Filter.extend({ 
    name: 'requresAuth', // name is used in controller for detect filter 
    async: true, // async mode 
    execution: Filter.Before, 
    handler(fragment, args, next) { 
    // Requesting server to check if user is authorised 
    $.ajax({ 
     url: '/auth', 
     success:() => { 
     this.isSignedIn = true; 
     next(); 
     }, 
     error:() => { 
     Backbone.navigate('login', true); 
     } 
    }); 
    }, 
}); 

или короткой синхронизации образом:

import { Filter } from 'marionette-lite'; 

const RequresAuthFilter = Filter.extend({ 
    name: 'requresAuth',  
    handler(fragment, args) { 
    if (!window.isSignedIn) { 
     Backbone.navigate('login', true); 
    } 
    }, 
}); 

И добавить этот фильтр, чтобы Controller как:

const AppController = Marionette.Object.extend({ 
    // Add available filters map 
    filtersMap: [ 
     new RequresAuthFilter() 
    ], 

    filters: { 
    // e.g. Action that need authentication and if user isn't 
    // authenticated gets redirect to login page 
    requresAuth: ['logout', 'private'], 
    }, 

    logout() { /* ... */ }, 
    private() { /* ... */ } 
}); 
Смежные вопросы