我有一个带有用户识别功能的Spring + AngularJS RestFul应用程序。
用户登录后,我会按以下方式存储此数据:
$window.sessionStorage.user
因为我希望在我的主控制器中实现的其他选项卡中有sessionStorage
这里提出的解决方案:https://stackoverflow.com/a/32766809/1281500
此外,在此控制器中,我会收听$stateChangeStart
个事件以检查用户是否已登录。如果用户未登录,我会将他重定向到相应的登录页面。
当我在资源管理器中打开一个新标签时出现问题。正如您在下面的代码中看到的那样,我从旧标签页获取$window.sessionStorage.user
变量到新标签页,如下所示:
else if (event.key == 'sessionStorage' && !$window.sessionStorage.length) {
// another tab sent data <- get it
var data = JSON.parse(event.newValue);
for (var key in data) {
$window.sessionStorage.setItem(key, data[key]);
}
但是$stateChangeStart
的代码是在上面的代码段之前执行的,因此$window.sessionStorage.user
尚未可用,并且即使用户已经登录,用户也总是被重定向到登录页面(至少在原始标签)
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
// if the user tries to access a restricted page an is not logged in, he is redirected to the login view
var restrictedPage = $.inArray(toState.name, ['login', 'sign-up']) === -1;
// "$window.sessionStorage.user" IS ALWAYS "UNDEFINED" just after a new tab is opened
if (restrictedPage && $window.sessionStorage.user === undefined) {
// Go to login page
}
});
完整的控制器代码如下。如何在$stateChangeStart
块中提供用户凭据?
(function() {
'use strict';
angular
.module('app.core')
.controller('CoreController', CoreController);
CoreController.$inject = ['$q', '$scope', '$rootScope', '$state', '$location', '$cookies', 'LoginService', '$window'];
function CoreController($q, $scope, $rootScope, $state, $location, $cookies, LoginService, $window) {
var vm = this;
var sessionStorage_transfer = function(event) {
if(!event) { event = $window.event; } // ie suq
if(!event.newValue) return; // do nothing if no value to work with
if (event.key == 'getSessionStorage') {
// another tab asked for the sessionStorage -> send it
$window.localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
// the other tab should now have it, so we're done with it.
$window.localStorage.removeItem('sessionStorage'); // <- could do short timeout as well.
} else if (event.key == 'sessionStorage' && !$window.sessionStorage.length) {
// another tab sent data <- get it
var data = JSON.parse(event.newValue);
for (var key in data) {
$window.sessionStorage.setItem(key, data[key]);
}
}
};
// listen for changes to localStorage
if($window.addEventListener) {
$window.addEventListener("storage", sessionStorage_transfer);
} else {
$window.attachEvent("onstorage", sessionStorage_transfer);
};
// ask other tabs for session storage (this is ONLY to trigger event)
if (!$window.sessionStorage.length) {
$window.localStorage.setItem('getSessionStorage', 'user');
$window.localStorage.removeItem('getSessionStorage', 'user');
};
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
// if the user tries to access a restricted page an is not logged in, he is redirected to the login view
var restrictedPage = $.inArray(toState.name, ['login', 'sign-up']) === -1;
if (restrictedPage && $window.sessionStorage.user === undefined) {
// Go to login page
}
});
}
})();
更新
我的应用程序是无状态,因此它按以下方式工作:
$window.sessionStorage.authToken
和$window.sessionStorage.authToken
之类的会话存储中。
我从另一个AngularJS控制器(LoginController)管理它:function login(valid) {
if(!valid) return;
LoginService.authenticate(vm.user)
.then(
function(user) {
var authToken = user.token;
$window.sessionStorage.authToken = authToken;
vm.authError = false;
if (vm.rememberMe) {
var now = new Date();
var expireDate = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate());
$cookies.put(AUTH_TOKEN_COOKIE, authToken, {'expires': expireDate});
}
LoginService.getUser()
.then(
function(user) {
$window.sessionStorage.user = user
$state.go('installations');
}
);
},
function(errAuthentication) {
vm.authError = true;
$window.sessionStorage.user = null;
}
);
}
所以基本上我的用户只存在于当前的sessionStorage
对象中,我没有检查用户是否登录的服务,我只检查我在第一次登录过程中存储的变量
我希望这有助于澄清我的过程。
非常感谢。
答案 0 :(得分:0)
确保您的控制器在其他模块之前运行真的很难。
如果您想在run module
上执行此操作之前执行此检查,请执行此操作。
angular
.module('myApp')
.run(runBlock)
.run(['mySessionChecker', '$rootScope', function (mySessionChecker, $rootScope ) {
$rootScope.$on("$locationChangeStart", function () {
//Service that checks if the user is logged or not
mySessionChecker.checkSession().then( function (auth) {
//Auth tells you if the user is logged in or not
console.log('User is '+auth);
doSomething();
})
});
}]);
function runBlock($log) {
$log.log('Angular's running');
}
Run Module
将在App Module
之后立即启动。
然后,例如,您可以emit an event
使用$rootScope
或使用Postal.js并对该信息执行某些操作。
我会创建一个Parent Controller
来拦截event
,我会扩展您需要进行检查的控制器,以了解用户是否已登录。
看看at this Q/A。
希望我能提供帮助。