javascript AngularJS - 防止未经身份验证的用户访问给定的路由

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15905547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 02:32:05  来源:igfitidea点击:

AngularJS - prevent not authenticated user from accessing given routes

javascriptsecurityangularjs

提问by Michal Ostruszka

In my app when user is logged in I have authServicewhich sets internal flag isAuthenticated. Now on every route change I have listener attached to $routeChangeStartevent which checks authService.isAuthenticated(). If no it should redirect to login route.

在我的应用程序中,当用户登录时,我authService设置了内部标志isAuthenticated。现在,在每次更改路线时,我都将侦听器附加到$routeChangeStart检查authService.isAuthenticated(). 如果没有,它应该重定向到登录路由。

Problem is when user makes page refresh (all the authServicesettings are lost) and it gets back to login again (while still having valid session on server). This is not what I want.

问题是当用户刷新页面(所有authService设置都丢失)并再次登录时(同时在服务器上仍然具有有效会话)。这不是我想要的。

What I'd like to do is to "block" route change until I get the info if user is authenticated (either from authServicewhich would be immediate, or from server if no info is available in authService, e.g. after refresh). I have such function in authService

我想要做的是“阻止”路由更改,直到我获得用户通过身份验证的信息(如果用户通过身份验证authService,则可以立即获取信息,或者如果在authService. 我有这样的功能authService

        // returns promise
        currentUser: function() {
            if (authService.isAuthenticated()) {
                return $q.when(authService.loggedUser);
            }
            return $http.get('/session').then(function(response) {
                authService.loggedUser = response.user;
                return $q.when(authService.loggedUser);
            });
        }

and would like to use it in event listener.

并想在事件监听器中使用它。

    $rootScope.$on("$routeChangeStart", function (event, next, current) {
        if(isRouteRestricted(next)) {
            authService.currentUser().then(null, function() {
                $location.path('/login');
            });
        }
    });

The thing is that it doesn't work as expected. I still get the target route visible for a very short time, and then user gets redirected. I believe it is due to nature of promises, but how to get rid of this "blink" effect?

问题是它没有按预期工作。我仍然在很短的时间内看到目标路线,然后用户被重定向。我相信这是由于承诺的性质,但如何摆脱这种“眨眼”效应?

回答by Roy Truelove

I'd do something like this in the top level controller, which would be the first controller that's called when the page is refreshed (apologize for typos in the js, I'm a coffeescript guy):

我会在顶层控制器中做这样的事情,这将是页面刷新时调用的第一个控制器(为 js 中的拼写错误道歉,我是一个咖啡脚本人):

var authCheck = function (event, next, current) {
    if(isRouteRestricted(next)) {
        authService.currentUser().then(null, function() {
            $location.path('/login');
        });
    }
}

authCheck(null, populateNextSomehow).then(function () {
    // all of your controller code, probably in a separate function
});

$rootScope.$on("$routeChangeStart", authCheck);

This will ensure that the controller code cannot be called until the authCheck is complete.

这将确保在 authCheck 完成之前无法调用控制器代码。

回答by Leo

To prevent a user for accessing routes you have to do several things:

为了防止用户访问路由,你必须做几件事:

First, set your routes and add a property like 'access' : allowAnonymous : true or false

首先,设置您的路线并添加一个类似“访问”的属性:allowAnonymous:true 或 false

// in app.js
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);       
myApp.config(function ($httpProvider, $routeProvider) {
   window.routes = {
        '/Login':
           { templateUrl: '/Account/Login',
             controller: 'AccountController',
             access : {allowAnonymous : true}
           },
        '/MembersPage':
           { templateUrl: '/Home/SomePage,
             controller: SomePageController',
             access: {allowAnonymous:false}
           }
         };

        for (var path in window.routes) {
           $routeProvider.when(path, window.routes[path]);
    }
    $routeProvider.otherwise({ redirectTo: '/Login' });
});   

Second, you must recognize an authenticated user:

其次,您必须识别经过身份验证的用户:

There are several ways for doing that but I prefer using the power of AngularJS throughout the use of ‘Services'. Therefore, I have created a ‘UserService' where we store the current user name and a value-indicating if is authenticated or not.

有几种方法可以做到这一点,但我更喜欢在“服务”的整个使用过程中使用 AngularJS 的强大功能。因此,我创建了一个“UserService”,用于存储当前用户名和一个指示是否经过身份验证的值。

// in UserService.js
myApp.factory('userService', function () {
var user = {
    isLogged: false,
    username: '',       
};

var reset = function() {
    user.isLogged = false;
    user.username = '';
};

return {
    user: user,
    reset : reset
  };
});

Last thing, capture route changes events and treat them correspondingly:

最后一件事,捕获路由更改事件并相应地处理它们:

After we have the service in place, it is time to use it and implement the check functionality for a route. There are several methods that intercept the route change event, but we are interested only in those that occur before the user was redirected so we can check if is authenticated: ‘$routeChangeStart', ‘$locationChangeStart'. Here we can check if the route that the user is going to allows anonymous access and if the user is logged in. If the case of failure, we can display an error message and redirect the user to the login page.

在我们准备好服务之后,是时候使用它并实现路由的检查功能了。有几种方法可以拦截路由更改事件,但我们只对在用户重定向之前发生的事件感兴趣,因此我们可以检查是否已通过身份验证:'$routeChangeStart'、'$locationChangeStart'。在这里,我们可以检查用户将要允许匿名访问的路由以及用户是否已登录。如果失败,我们可以显示错误消息并将用户重定向到登录页面。

// in RootController.js
myApp.controller('RootController',
function ($scope, $route, $routeParams, $location, $rootScope, authenticationService,   
userService, toaster) {
 $scope.user = userService.user;
 $scope.$on('$routeChangeStart', function (e, next, current) {               
     if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) {
                $location.path("/Login");                   
            }
        });

        $scope.logout = function () {
            authenticationService.logout()
                .success(function (response) {
                    userService.reset();                       
                    toaster.pop("info", 'You are logged out.', '');
                });
        };

 $rootScope.$on("$locationChangeStart", function (event, next, current) {
  for (var i in window.routes) {
    if (next.indexOf(i) != -1) {
     if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) {
          toaster.pop("error", 'You are not logged in!', '');
             $location.path("/Login");                                                 
                    }
                }
            }
        });
    });

Complete article is here: http://net-daylight.blogspot.ro/

完整的文章在这里:http: //net-daylight.blogspot.ro/

Hope it helps!

希望能帮助到你!