代码之家  ›  专栏  ›  技术社区  ›  user441521

路由重定向中来自$http调用的用户值

  •  0
  • user441521  · 技术社区  · 7 年前

    我正在编写一个小的AngularJS应用程序,它有一个登录视图和一个主视图,配置如下:

    $routeProvider
     .when('/main' , {templateUrl: 'partials/main.html',  controller: MainController})
     .when('/login', {templateUrl: 'partials/login.html', controller: LoginController})
     .otherwise({redirectTo: '/login'});
    

    我的LoginController检查user/pass组合并在$rootScope上设置一个属性,反映以下内容:

    function LoginController($scope, $location, $rootScope) {
     $scope.attemptLogin = function() {
       if ( $scope.username == $scope.password ) { // test
            $rootScope.loggedUser = $scope.username;
            $location.path( "/main" );
        } else {
            $scope.loginError = "Invalid user/pass.";
        }
    }
    

    一切正常,但如果我 http://localhost/#/main 我最终绕过了登录屏幕。我想写一些类似于“每当路由改变时,如果$rootScope.loggedUser为null,则重定向到/login”

    ...

    0 回复  |  直到 11 年前
        1
  •  514
  •   Alton Developer st.never    7 年前

    在浏览了一些文档和源代码之后,我想我已经开始工作了。也许这对其他人有用?

    我在模块配置中添加了以下内容:

    angular.module(...)
     .config( ['$routeProvider', function($routeProvider) {...}] )
     .run( function($rootScope, $location) {
    
        // register listener to watch route changes
        $rootScope.$on( "$routeChangeStart", function(event, next, current) {
          if ( $rootScope.loggedUser == null ) {
            // no logged user, we should be going to #login
            if ( next.templateUrl != "partials/login.html" ) {
              // not going to #login, we should redirect now
              $location.path( "/login" );
            }
          }         
        });
     })
    

    有一件事看起来很奇怪,那就是我必须测试部分名称( login.html

        2
  •  94
  •   Ahmed Alnabhan Nikolay Popov    9 年前

    在路由配置的'resolve'中指定一个函数,在函数load and check data中指定所有重定向。如果需要加载数据,则返回一个承诺,如果需要在这之前执行重定向-拒绝承诺。 所有细节可在 $routerProvider $q 文档页。

    'use strict';
    
    var app = angular.module('app', [])
        .config(['$routeProvider', function($routeProvider) {
            $routeProvider
                .when('/', {
                    templateUrl: "login.html",
                    controller: LoginController
                })
                .when('/private', {
                    templateUrl: "private.html",
                    controller: PrivateController,
                    resolve: {
                        factory: checkRouting
                    }
                })
                .when('/private/anotherpage', {
                    templateUrl:"another-private.html",
                    controller: AnotherPriveController,
                    resolve: {
                        factory: checkRouting
                    }
                })
                .otherwise({ redirectTo: '/' });
        }]);
    
    var checkRouting= function ($q, $rootScope, $location) {
        if ($rootScope.userProfile) {
            return true;
        } else {
            var deferred = $q.defer();
            $http.post("/loadUserProfile", { userToken: "blah" })
                .success(function (response) {
                    $rootScope.userProfile = response.userProfile;
                    deferred.resolve(true);
                })
                .error(function () {
                    deferred.reject();
                    $location.path("/");
                 });
            return deferred.promise;
        }
    };
    

    对讲俄语的人来说,habr上有一个帖子 Вариант условного раутинга в AngularJS

        3
  •  61
  •   T J    9 年前

    我也试着这么做。在与同事合作后,我想出了另一个更简单的解决方案。我有一块手表 $location.path() . 这就成功了。我刚刚开始学习AngularJS,发现它更清晰易读。

    $scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
        if ($scope.loggedIn == false && newValue != '/login'){  
                $location.path('/login');  
        }  
    });
    
        4
  •  37
  •   Oran Dennison    10 年前

    实现登录重定向的另一种方法是将事件和拦截器用作 described here . 本文描述了一些附加的优点,如检测何时需要登录、将请求排队以及在登录成功后重播它们。

    here 并查看演示源代码 here .

        5
  •  34
  •   AJcodez    11 年前

    1.设置全局当前用户。

    // AuthService.js
    
      // auth successful
      $rootScope.user = user
    

    2.在每个受保护的路由上设置auth函数。

    // AdminController.js
    
    .config(function ($routeProvider) {
      $routeProvider.when('/admin', {
        controller: 'AdminController',
        auth: function (user) {
          return user && user.isAdmin
        }
      })
    })
    

    3.检查每个路线更改的身份验证。

    // index.js
    
    .run(function ($rootScope, $location) {
      $rootScope.$on('$routeChangeStart', function (ev, next, curr) {
        if (next.$$route) {
          var user = $rootScope.user
          var auth = next.$$route.auth
          if (auth && !auth(user)) { $location.path('/') }
        }
      })
    })
    

        6
  •  27
  •   T J    9 年前

    我是这样做的,以防对任何人都有帮助:

    publicAccess 我希望对公众开放的几个路由的属性(如登录或注册):

    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: 'HomeCtrl'
        })
        .when('/login', {
            templateUrl: 'views/login.html',
            controller: 'LoginCtrl',
            publicAccess: true
        })
    

    然后在run块中,我在 $routeChangeStart '/login' 除非用户具有访问权限或路由可公开访问:

    angular.module('myModule').run(function($rootScope, $location, user, $route) {
    
        var routesOpenToPublic = [];
        angular.forEach($route.routes, function(route, path) {
            // push route onto routesOpenToPublic if it has a truthy publicAccess value
            route.publicAccess && (routesOpenToPublic.push(path));
        });
    
        $rootScope.$on('$routeChangeStart', function(event, nextLoc, currentLoc) {
            var closedToPublic = (-1 === routesOpenToPublic.indexOf($location.path()));
            if(closedToPublic && !user.isLoggedIn()) {
                $location.path('/login');
            }
        });
    })
    

    isLoggedIn 其他任何事情。。。只是展示另一种方法。

        7
  •  9
  •   Christopher Armstrong    12 年前

    我是用拦截器做的。我已经创建了一个库文件,可以添加到index.html文件中。这样,您就可以对rest服务调用进行全局错误处理,而不必单独关心所有错误。再往下,我还粘贴了我的基本身份验证登录库。在那里你可以看到,我也检查了401错误,并重定向到一个不同的位置。请参阅lib/ea-basic-auth-login.js

    /**
    * @ngdoc overview
    * @name http-error-handling
    * @description
    *
    * Module that provides http error handling for apps.
    *
    * Usage:
    * Hook the file in to your index.html: <script src="lib/http-error-handling.js"></script>
    * Add <div class="messagesList" app-messages></div> to the index.html at the position you want to
    * display the error messages.
    */
    (function() {
    'use strict';
    angular.module('http-error-handling', [])
        .config(function($provide, $httpProvider, $compileProvider) {
            var elementsList = $();
    
            var showMessage = function(content, cl, time) {
                $('<div/>')
                    .addClass(cl)
                    .hide()
                    .fadeIn('fast')
                    .delay(time)
                    .fadeOut('fast', function() { $(this).remove(); })
                    .appendTo(elementsList)
                    .text(content);
            };
    
            $httpProvider.responseInterceptors.push(function($timeout, $q) {
                return function(promise) {
                    return promise.then(function(successResponse) {
                        if (successResponse.config.method.toUpperCase() != 'GET')
                            showMessage('Success', 'http-success-message', 5000);
                        return successResponse;
    
                    }, function(errorResponse) {
                        switch (errorResponse.status) {
                            case 400:
                                showMessage(errorResponse.data.message, 'http-error-message', 6000);
                                    }
                                }
                                break;
                            case 401:
                                showMessage('Wrong email or password', 'http-error-message', 6000);
                                break;
                            case 403:
                                showMessage('You don\'t have the right to do this', 'http-error-message', 6000);
                                break;
                            case 500:
                                showMessage('Server internal error: ' + errorResponse.data.message, 'http-error-message', 6000);
                                break;
                            default:
                                showMessage('Error ' + errorResponse.status + ': ' + errorResponse.data.message, 'http-error-message', 6000);
                        }
                        return $q.reject(errorResponse);
                    });
                };
            });
    
            $compileProvider.directive('httpErrorMessages', function() {
                return {
                    link: function(scope, element, attrs) {
                        elementsList.push($(element));
                    }
                };
            });
        });
    })();
    

    css/http-error-handling.css文件

    .http-error-message {
        background-color: #fbbcb1;
        border: 1px #e92d0c solid;
        font-size: 12px;
        font-family: arial;
        padding: 10px;
        width: 702px;
        margin-bottom: 1px;
    }
    
    .http-error-validation-message {
        background-color: #fbbcb1;
        border: 1px #e92d0c solid;
        font-size: 12px;
        font-family: arial;
        padding: 10px;
        width: 702px;
        margin-bottom: 1px;
    }
    
    http-success-message {
        background-color: #adfa9e;
        border: 1px #25ae09 solid;
        font-size: 12px;
        font-family: arial;
        padding: 10px;
        width: 702px;
        margin-bottom: 1px;
    }
    

    索引.html

    <!doctype html>
    <html lang="en" ng-app="cc">
        <head>
            <meta charset="utf-8">
            <title>yourapp</title>
            <link rel="stylesheet" href="css/http-error-handling.css"/>
        </head>
        <body>
    
    <!-- Display top tab menu -->
    <ul class="menu">
      <li><a href="#/user">Users</a></li>
      <li><a href="#/vendor">Vendors</a></li>
      <li><logout-link/></li>
    </ul>
    
    <!-- Display errors -->
    <div class="http-error-messages" http-error-messages></div>
    
    <!-- Display partial pages -->
    <div ng-view></div>
    
    <!-- Include all the js files. In production use min.js should be used -->
    <script src="lib/angular114/angular.js"></script>
    <script src="lib/angular114/angular-resource.js"></script>
    <script src="lib/http-error-handling.js"></script>
    <script src="js/app.js"></script>
    <script src="js/services.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/filters.js"></script>
    

    /**
    * @ngdoc overview
    * @name ea-basic-auth-login
    * @description
    *
    * Module that provides http basic authentication for apps.
    *
    * Usage:
    * Hook the file in to your index.html: <script src="lib/ea-basic-auth-login.js">  </script>
    * Place <ea-login-form/> tag in to your html login page
    * Place <ea-logout-link/> tag in to your html page where the user has to click to logout
    */
    (function() {
    'use strict';
    angular.module('ea-basic-auth-login', ['ea-base64-login'])
        .config(['$httpProvider', function ($httpProvider) {
            var ea_basic_auth_login_interceptor = ['$location', '$q', function($location, $q) {
                function success(response) {
                    return response;
                }
    
                function error(response) {
                    if(response.status === 401) {
                        $location.path('/login');
                        return $q.reject(response);
                    }
                    else {
                        return $q.reject(response);
                    }
                }
    
                return function(promise) {
                    return promise.then(success, error);
                }
            }];
            $httpProvider.responseInterceptors.push(ea_basic_auth_login_interceptor);
        }])
        .controller('EALoginCtrl', ['$scope','$http','$location','EABase64Login', function($scope, $http, $location, EABase64Login) {
            $scope.login = function() {
                $http.defaults.headers.common['Authorization'] = 'Basic ' + EABase64Login.encode($scope.email + ':' + $scope.password);
                $location.path("/user");
            };
    
            $scope.logout = function() {
                $http.defaults.headers.common['Authorization'] = undefined;
                $location.path("/login");
            };
        }])
        .directive('eaLoginForm', [function() {
            return {
                restrict:   'E',
                template:   '<div id="ea_login_container" ng-controller="EALoginCtrl">' +
                            '<form id="ea_login_form" name="ea_login_form" novalidate>' +
                            '<input id="ea_login_email_field" class="ea_login_field" type="text" name="email" ng-model="email" placeholder="E-Mail"/>' +
                            '<br/>' +
                            '<input id="ea_login_password_field" class="ea_login_field" type="password" name="password" ng-model="password" placeholder="Password"/>' +
                            '<br/>' +
                            '<button class="ea_login_button" ng-click="login()">Login</button>' +
                            '</form>' +
                            '</div>',
                replace: true
            };
        }])
        .directive('eaLogoutLink', [function() {
            return {
                restrict: 'E',
                template: '<a id="ea-logout-link" ng-controller="EALoginCtrl" ng-click="logout()">Logout</a>',
                replace: true
            }
        }]);
    
    angular.module('ea-base64-login', []).
        factory('EABase64Login', function() {
            var keyStr = 'ABCDEFGHIJKLMNOP' +
                'QRSTUVWXYZabcdef' +
                'ghijklmnopqrstuv' +
                'wxyz0123456789+/' +
                '=';
    
            return {
                encode: function (input) {
                    var output = "";
                    var chr1, chr2, chr3 = "";
                    var enc1, enc2, enc3, enc4 = "";
                    var i = 0;
    
                    do {
                        chr1 = input.charCodeAt(i++);
                        chr2 = input.charCodeAt(i++);
                        chr3 = input.charCodeAt(i++);
    
                        enc1 = chr1 >> 2;
                        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                        enc4 = chr3 & 63;
    
                        if (isNaN(chr2)) {
                            enc3 = enc4 = 64;
                        } else if (isNaN(chr3)) {
                            enc4 = 64;
                        }
    
                        output = output +
                            keyStr.charAt(enc1) +
                            keyStr.charAt(enc2) +
                            keyStr.charAt(enc3) +
                            keyStr.charAt(enc4);
                        chr1 = chr2 = chr3 = "";
                        enc1 = enc2 = enc3 = enc4 = "";
                    } while (i < input.length);
    
                    return output;
                },
    
                decode: function (input) {
                    var output = "";
                    var chr1, chr2, chr3 = "";
                    var enc1, enc2, enc3, enc4 = "";
                    var i = 0;
    
                    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
                    var base64test = /[^A-Za-z0-9\+\/\=]/g;
                    if (base64test.exec(input)) {
                        alert("There were invalid base64 characters in the input text.\n" +
                            "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                            "Expect errors in decoding.");
                    }
                    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    
                    do {
                        enc1 = keyStr.indexOf(input.charAt(i++));
                        enc2 = keyStr.indexOf(input.charAt(i++));
                        enc3 = keyStr.indexOf(input.charAt(i++));
                        enc4 = keyStr.indexOf(input.charAt(i++));
    
                        chr1 = (enc1 << 2) | (enc2 >> 4);
                        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                        chr3 = ((enc3 & 3) << 6) | enc4;
    
                        output = output + String.fromCharCode(chr1);
    
                        if (enc3 != 64) {
                            output = output + String.fromCharCode(chr2);
                        }
                        if (enc4 != 64) {
                            output = output + String.fromCharCode(chr3);
                        }
    
                        chr1 = chr2 = chr3 = "";
                        enc1 = enc2 = enc3 = enc4 = "";
    
                    } while (i < input.length);
    
                    return output;
                }
            };
        });
    })();
    
        8
  •  8
  •   Ben Cochrane    9 年前

    在app.js文件中:

    .run(["$rootScope", "$state", function($rootScope, $state) {
    
          $rootScope.$on('$locationChangeStart', function(event, next, current) {
            if (!$rootScope.loggedUser == null) {
              $state.go('home');
            }    
          });
    }])
    
        9
  •  4
  •   T J    9 年前

    angular-ui-router . 为此,我们有了 $state.go("target_view")

     ---- app.js -----
    
     var app = angular.module('myApp', ['ui.router']);
    
     app.config(function ($stateProvider, $urlRouterProvider) {
    
        // Otherwise
        $urlRouterProvider.otherwise("/");
    
        $stateProvider
                // Index will decide if redirects to Login or Dashboard view
                .state("index", {
                     url: ""
                     controller: 'index_controller'
                  })
                .state('dashboard', {
                    url: "/dashboard",
                    controller: 'dashboard_controller',
                    templateUrl: "views/dashboard.html"
                  })
                .state('login', {
                    url: "/login",
                    controller: 'login_controller',
                    templateUrl: "views/login.html"
                  });
     });
    
     // Associate the $state variable with $rootScope in order to use it with any controller
     app.run(function ($rootScope, $state, $stateParams) {
            $rootScope.$state = $state;
            $rootScope.$stateParams = $stateParams;
        });
    
     app.controller('index_controller', function ($scope, $log) {
    
        /* Check if the user is logged prior to use the next code */
    
        if (!isLoggedUser) {
            $log.log("user not logged, redirecting to Login view");
            // Redirect to Login view 
            $scope.$state.go("login");
        } else {
            // Redirect to dashboard view 
            $scope.$state.go("dashboard");
        }
    
     });
    
    ----- HTML -----
    
    <!DOCTYPE html>
    <html>
        <head>
            <title>My WebSite</title>
    
            <meta charset="utf-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
            <meta name="description" content="MyContent">
            <meta name="viewport" content="width=device-width, initial-scale=1">
    
            <script src="js/libs/angular.min.js" type="text/javascript"></script>
            <script src="js/libs/angular-ui-router.min.js" type="text/javascript"></script>
            <script src="js/app.js" type="text/javascript"></script>
    
        </head>
        <body ng-app="myApp">
            <div ui-view></div>
        </body>
    </html>
    
        10
  •  3
  •   Ivan HuÅ¡njak    10 年前

    $routeChangeStart

    您不能确定控制器将在 被触发——事实上它不会被加载。这意味着您无法访问的属性 next 路线式 locals $$route 因为它们还没有安装好。

    app.config(["$routeProvider", function($routeProvider) {
        $routeProvider.when("/foo", {
            controller: "Foo",
            resolve: {
                controller: ["$q", function($q) {
                    var deferred = $q.defer();
                    require(["path/to/controller/Foo"], function(Foo) {
                        // now controller is loaded
                        deferred.resolve();
                    });
                    return deferred.promise;
                }]
            }
        });
    }]);
    
    app.run(["$rootScope", function($rootScope) {
        $rootScope.$on("$routeChangeStart", function(event, next, current) {
            console.log(next.$$route, next.locals); // undefined, undefined
        });
    }]);
    

    这意味着您不能在其中检查访问权限。

    app.config(["$routeProvider", function($routeProvider) {
        $routeProvider.when("/foo", {
            controller: "Foo",
            resolve: {
                controller: ["$q", function($q) {
                    var deferred = $q.defer();
                    require(["path/to/controller/Foo"], function(Foo) {
                        // now controller is loaded
                        deferred.resolve();
                    });
                    return deferred.promise;
                }],
                access: ["$q", function($q) {
                    var deferred = $q.defer();
                    if (/* some logic to determine access is granted */) {
                        deferred.resolve();
                    } else {
                        deferred.reject("You have no access rights to go there");
                    }
                    return deferred.promise;
                }],
            }
        });
    }]);
    
    app.run(["$rootScope", function($rootScope) {
        $rootScope.$on("$routeChangeError", function(event, next, current, error) {
            console.log("Error: " + error); // "Error: You have no access rights to go there"
        });
    }]);
    

    注意这里不是使用事件 $routeChange开始 $routeChangeError

        11
  •  -4
  •   Dixit Hasija    10 年前
        $routeProvider
     .when('/main' , {templateUrl: 'partials/main.html',  controller: MainController})
     .when('/login', {templateUrl: 'partials/login.html', controller: LoginController}).
     .when('/login', {templateUrl: 'partials/index.html', controller: IndexController})
     .otherwise({redirectTo: '/index'});