Uso l'autorizzazione basata sui ruoli sul backend e sul frontend. Dal momento che sto usando UI-router per il routing, la miglior risorsa che ho trovato (e migliorato per le mie esigenze) è questo articolo:
collegamento scaduto
Se si utilizza interfaccia utente del router, sicuramente check it out. Fondamentalmente è necessario impostare la sicurezza dei percorsi e intercettare tutte le modifiche del percorso. L'articolo include anche una direttiva per nascondere gli elementi dell'interfaccia utente, se l'utente non ha il permesso di accedere al contenuto dietro di esso.
Edit: Aggiunta di un codice.
In primo luogo, è necessario che le autorizzazioni dell'utente siano memorizzate da qualche parte, ad es.sul oggetto utente serializzato in localStorage:
{"id":1,"name":"user","created_at":"2016-04-17 18:58:19","gender":"m","roles":["admin"]}
Poi, ci sono due parti importanti:
- direttiva - per determinare se l'elemento deve essere visibile o meno sulla base di autorizzazione assegnato
- servizi - per gestire il controllo delle autorizzazioni
direttiva:
(function() {
'use strict';
angular
.module('app')
.directive('access', access);
/** @ngInject */
function access(authorization) {
var directive = {
restrict: 'A',
link: linkFunc,
};
return directive;
/** @ngInject */
function linkFunc($scope, $element, $attrs) {
var makeVisible = function() {
$element.removeClass('hidden');
};
var makeHidden = function() {
$element.addClass('hidden');
};
var determineVisibility = function (resetFirst) {
var result;
if (resetFirst) {
makeVisible();
}
result = authorization.authorize(true, roles, $attrs.accessPermissionType);
if (result === authorization.constants.authorised) {
makeVisible();
} else {
makeHidden();
}
};
var roles = $attrs.access.split(',');
if (roles.length > 0) {
determineVisibility(true);
}
}
}
})();
È necessario impostare il CSS in modo che gli elementi con classe hidden
non siano visibili.
Servizio:
(function() {
'use strict';
angular
.module('app')
.factory('authorization', authorization);
/** @ngInject */
function authorization($rootScope) {
var service = {
authorize: authorize,
constants: {
authorised: 0,
loginRequired: 1,
notAuthorised: 2
}
};
return service;
function authorize(loginRequired, requiredPermissions, permissionCheckType) {
var result = service.constants.authorised,
user = $rootScope.currentUser,
loweredPermissions = [],
hasPermission = true,
permission;
permissionCheckType = permissionCheckType || 'atLeastOne';
if (loginRequired === true && user === undefined) {
result = service.constants.loginRequired;
} else if ((loginRequired === true && user !== undefined) &&
(requiredPermissions === undefined || requiredPermissions.length === 0)) {
result = service.constants.authorised;
} else if (requiredPermissions) {
loweredPermissions = [];
angular.forEach(user.roles, function (permission) {
loweredPermissions.push(permission.toLowerCase());
});
for (var i = 0; i < requiredPermissions.length; i += 1) {
permission = requiredPermissions[i].toLowerCase();
if (permissionCheckType === 'combinationRequired') {
hasPermission = hasPermission && loweredPermissions.indexOf(permission) > -1;
// if all the permissions are required and hasPermission is false there is no point carrying on
if (hasPermission === false) {
break;
}
} else if (permissionCheckType === 'atLeastOne') {
hasPermission = loweredPermissions.indexOf(permission) > -1;
// if we only need one of the permissions and we have it there is no point carrying on
if (hasPermission) {
break;
}
}
}
result = hasPermission ?
service.constants.authorised :
service.constants.notAuthorised;
}
return result;
}
}
})();
Ora, è possibile utilizzare la direttiva per mostrare/nascondere elemento:
<a ui-sref="app.administration" class="btn btn-primary pull-right" access="admin">Administration</a>
Naturalmente questo nasconde solo l'elemento di DOM, quindi è necessario fare il controllo dell'autorizzazione anche sul server.
Questa prima parte ha risolto la visualizzazione/occultamento degli elementi nell'interfaccia utente, ma è anche possibile proteggere i percorsi delle app.
definizione della rotta:
(function() {
'use strict';
angular
.module('app')
.config(routeConfig);
/** @ngInject */
function routeConfig($stateProvider) {
$stateProvider
.state('app.dashboard', {
url: '/dashboard',
data: {
access: {
loginRequired: true
}
},
templateUrl: 'template_path',
controller: 'DashboardController as vm'
}
}
})();
e ora basta controllare il permesso in $stateChangeStart
evento
(function() {
'use strict';
angular
.module('app')
.run(runBlock);
/** @ngInject */
function runBlock($rootScope, $state, authorization) {
$rootScope.$on('$stateChangeStart', function(event, toState) {
// route authorization check
if (toState.data !== undefined && toState.data.access !== undefined) {
authorised = authorization.authorize(toState.data.access.loginRequired,
toState.data.access.requiredPermissions,
toState.data.access.permissionCheckType);
if (authorised === authorization.constants.loginRequired) {
event.preventDefault();
$state.go('app.login');
} else if (authorised === authorization.constants.notAuthorised) {
event.preventDefault();
$state.go('app.dashboard');
}
}
});
}
})();
Grazie @ sh-ado-w, sarei attuazione di tale soluzione si è accennato in precedenza . Ti farò sapere se funziona o no. – CalmWinds
Link non funziona più. Meglio pubblicare contenuti in SO che link al di fuori di esso. – eabates
Ho aggiunto il codice dalla mia applicazione che, credo, era basato su quell'articolo. – Adrian