我有一个angularjs ui-router情况,其中:
这是一个棘手的情况,我似乎无法做到恰到好处。我当前的代码确实有效,但是......它必须显示“登录”#39;导航前一秒钟的页面。发生这种情况是因为我不得不以某种方式启动$stateChangeStart
。
var app = angular.module('myapp', ['ui.router']);
// handle default states based on authentication,
// default properties set in user profile, or
// or just redirect to 'apps' page
var authd = false,
defaultDashboard = undefined,
defaultFn = function($injector){
// required to get location since loaded before app
var $location = $injector.get('$location');
// if the user has a default dashboard, navigate to that
if(defaultDashboard){
$location.path('workspace/' + defaultDashboard);
} else if(authd) {
// if the user is auth'd but doesn't have url
$location.path('home');
} else {
// if we aren't auth'd yet
$location.path('login');
}
};
app.config(function ($urlRouterProvider, $locationProvider, $stateProvider) {
$locationProvider.html5Mode(true);
app.stateProvider = $stateProvider;
$urlRouterProvider.otherwise(function($injector){
defaultFn($injector);
});
});
app.run(function ($rootScope, $q, $location, $state, $stateParams, $injector, security) {
var deregister = $rootScope.$on("$stateChangeStart", function () {
// authorize is a AJAX request to pass session token and return profile for user
security.authorize().success(function(d){
// set some local flags for defaultFn
authd = true;
defaultDashboard = d.defaultDashboard;
// de-register the start event after login to prevent further calls
deregister();
// switch to default view after login
if($location.$$url === "/login" ||
$location.$$url === "/"){
defaultFn($injector);
}
}).error(function(){
$location.path('login');
});
});
});
我使用一个接受器来处理401s,如:
var module = angular.module('security.interceptor', []);
// This http interceptor listens for authentication failures
module.factory('securityInterceptor', function($injector, $location) {
return function(promise) {
// Intercept failed requests
return promise.then(null, function(originalResponse) {
if(originalResponse.status === 401) {
$location.path('/login');
}
return promise;
});
};
});
// We have to add the interceptor to the queue as a string because the
// interceptor depends upon service instances that are not available in the config block.
module.config(function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
$httpProvider.responseInterceptors.push('securityInterceptor');
});
任何人都有类似的案例并找到了更好的解决方案吗?
答案 0 :(得分:5)
我想出了我的解决方案:
app.config(function ($urlRouterProvider, $locationProvider, $stateProvider) {
$locationProvider.html5Mode(true);
// placeholder
$stateProvider.state('welcome', {
url: '/'
});
$urlRouterProvider.otherwise('404');
});
app.run(function ($rootScope, $q, $location, $state, $stateParams, security, $urlRouter) {
var deregister = $rootScope.$on("$stateChangeStart", function (event) {
// stop the change!
event.preventDefault();
security.authorize().success(function(d){
// if we don't have a previous url
if($location.$$url === "/" || $location.$$url === "/login"){
// If user has a preset home
if(d.defaultDashboard){
$location.path('workspace/' + d.defaultDashboard);
} else {
$location.path('welcome');
}
} else {
// if we do, then continue
$urlRouter.sync();
}
}).error(function(){
// redirect to home
$location.path('login');
});
// deregister the listener
deregister();
});
});
基本上,为空路线创建空路线解决了我的问题。有趣。