我正在使用 ui-router
(0.2.18),并且我想在用户未登录或不允许查看某些内容时限制对某些页面的访问。
我想出了下面的解决方案,但即使我没有登录,我仍然可以看到该页面一秒钟,然后我被重定向到 /login
页面。显然这很难看,我如何在加载页面之前进行检查?我正在尝试找到一个模块化的解决方案。
我进行后端检查,因此如果用户未登录,他/她无论如何都看不到任何内容,但是这个重定向问题让我感到困扰。
工厂
angular.module('app.index').factory('Auth', ["$http", "$window", function($http, $window) {
return {
isLoggedIn: function() {
return $http.get('/whoami').then(function(rt) {
if (rt.data.length) {
return true;
}
}).catch(function(err) {
return $window.location.href = 'http://localhost/login';
});
}
};
}]);
路线
angular.module('app.index.routes')
.run(
['$rootScope', '$state', '$stateParams', 'Auth',
function($rootScope, $state, $stateParams, Auth) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
if (toState.authenticate && !Auth.isLoggedIn()) {
console.log("please log in");
event.preventDefault();
} else {
console.log("you are logged in");
}
});
}
]
)
.config(
['$stateProvider', '$urlRouterProvider', '$locationProvider',
function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('index', {
url: '/test',
authenticate: true, // if this is true, `toState.authenticate` becomes true
template: "auth check"
});
}
]);
最佳答案
这是一个基于我检查状态的应用程序的示例。主要需要注意的是:
在状态上使用数据属性,因为子状态将继承其父状态的数据属性。这将允许所需的身份验证免费传播到子状态。
您正在检查用户登录是否正在使用 http 请求,这很糟糕,因为您会因延迟而遇到延迟。您应该使用服务变量或 session 存储来保存用户是否登录的标志,这样检查身份验证状态时就不会出现延迟。
- 使用 $state.go() 而不是设置 window.location 可能是更好的解决方案,因为您使用的是 html5 模式,它可能会将其解释为进行完整页面重新加载而不是哈希更改(对此不确定我一般不使用html5模式)。
希望这有帮助:
var core = angular.module("core", ["ui.router", "ngStorage"]);
core.run(["$rootScope", "$state", "AuthService", function ($rootScope, $state, Auth) {
$rootScope.$on("$stateChangeStart", function (evt, toState, toParams, fromState, fromParams) {
if (toState.name !== "login" &&
_.get(toState, "data.authenticate", false) &&
!Auth.isLoggedIn()) {
$state.go("login");
evt.preventDefault();
}
});
}]);
core.factory("AuthService", ["$http", "$sessionStorage", "$q",
function ($http, $sessionStorage, $q) {
return {
isLoggedIn: function () {
return !!$sessionStorage.user;
},
localLogin: function (email, password) {
var def = $q.defer();
$http
.post("/login", { email: email, password: password })
.then(function (res) {
if (_.has(res, "data.error")) {
def.reject(res.data.error);
} else {
$sessionStorage.user = res.data.user;
def.resolve();
}
})
.catch(function (err) {
def.reject(err);
});
return def.promise;
}
};
}]);
core.config(["$stateProvider", "$urlRouterProvider",
function ($stateProvider, $urlRouterProvider) {
// For all unmatched url, redirect to /login
$urlRouterProvider.otherwise("/login");
$stateProvider
.state("login", {
url: "/login",
views: {
"": {
templateUrl: "app/core/templates/login.html",
controller: "core.login.ctrl",
controllerAs: "vm"
}
}
})
.state("profile", {
url: "/profile",
data: {
authenticate: true
},
views: {
"": {
templateUrl: "app/core/templates/profile.html",
controller: "core.ctrl",
controllerAs: "vm"
}
}
});
}]);
关于angularjs - 如果用户未经过身份验证,Angular ui-router 会立即重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36048766/