조건에 따라 특정 경로로 리디렉션


493

로그인보기와 메인보기가있는 작은 AngularJS 앱을 작성 중입니다.

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

내 LoginController는 사용자 / 패스 조합을 확인하고이를 반영하여 $ 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으로 경로 재 지정"과 같은 내용을 작성하고 싶었습니다.

...

... 잠깐만 어떻게 든 경로 변경을들을 수 있습니까? 어쨌든이 질문을 게시하고 계속 볼 것입니다.


3
명확히하기 위해 : 아래의 많은 솔루션이 잘 작동하지만 최근에 @Oran의 답변을 수락하는 경향이 있습니다. 즉, 민감한 URL을 요청할 때 서버가 401 코드로 응답하고 해당 정보를 사용하여 제어하십시오. 클라이언트의 "로그인 상자". (그러나 배심원은 여전히 ​​"나를 위해 거부 된 요청을 큐잉하고 나중에 다시 발행하는"비트에 여전히 빠져 있습니다.)
st.never

답변:


510

일부 문서와 소스 코드를 살펴본 후 작동한다고 생각합니다. 아마도 이것은 다른 사람에게 유용할까요?

모듈 구성에 다음을 추가했습니다.

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는 "다음"Route 객체에 URL이나 다른 것이 없기 때문에 부분 이름 ( ) 을 테스트 해야한다는 것입니다. 더 좋은 방법이 있을까요?


13
멋진 사람, 솔루션을 공유해 주셔서 감사합니다. 주의 할 점 : 현재 버전에서, 그것은 "다음 $ route.templateUrl."입니다
doubledriscoll

5
Chrome 관리자에서 네트워크 요청을 보면 (사용자가 로그인하지 않았기 때문에) 리디렉션되는 경로가 계속 호출되고 응답이 브라우저로 전송 된 다음 리디렉션 된 경로 '/ login'이 호출됩니다. 따라서 로그인하지 않은 사용자는 액세스해서는 안되는 경로에 대한 응답을 볼 수 있으므로이 방법은 좋지 않습니다.
sonicboom 2016 년

34
$ routeChangeStart 대신 $ locationChangeStart를 사용하여 경로가 호출되지 않고 인증되지 않은 사용자가 액세스해서는 안되는 콘텐츠를 볼 수 없도록합니다.
sonicboom 2016 년

17
이것이 클라이언트라는 것을 기억하십시오. 서버 쪽 장벽도 있어야합니다.
Neikos

2
@sonicboom $ locationChangeStart는 모든 라우트에 인증이 필요한 것은 아니므로 $ routeChangeStart를 사용하면 라우트 객체에 대한 메타 데이터를 인증 할 수 있는지 여부 또는 해당 라우트에 필요한 역할과 같은 메타 데이터를 가질 수 있습니다. 서버는 인증되지 않은 내용을 표시하지 않아야하며 경로가 변경 될 때까지 AngularJS가 처리를 시작하지 않으므로 아무 것도 표시하지 않아야합니다.
크리스 니콜

93

다음은 '해결'구성 속성과 데이터에 따라 라우팅 및 라우팅 규칙에 대한 최종 데이터로드를 가능하게하는 '약속 성'을 갖춘보다 우아하고 유연한 솔루션입니다.

라우팅 설정에서 '해결'에 기능을 지정하고 데이터를로드 및 확인하는 기능에 모든 리디렉션을 수행하십시오. 데이터를로드 해야하는 경우 리디렉션을 수행 해야하는 경우 약속을 반환합니다. 모든 세부 사항은 $ 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 "에 대한 게시물이 있습니다.


1
checkRouting 함수가 공장에 매핑되는 이유는 무엇입니까? 매핑 된 것이 중요합니까?
honkskillet

@honkskillet : 각도 $ routeProvider 문서에서 : "factory-{string | function} : 문자열 인 경우 서비스의 별명입니다. 그렇지 않으면 함수 인 경우 삽입되고 리턴 값이 종속성으로 처리됩니다. ngRoute. $ routeParams는 여전히 이러한 해결 함수 내에서 이전 경로를 참조하므로 $ route.current.params를 사용하여 새 경로 매개 변수에 액세스하십시오. 대신에. " 또한 해결에 관한 문서에서 : "약속이 거부되면 $ routeChangeError 이벤트가 시작됩니다."
Tim Perry

ui.router사용 $stateProvider 하는 경우 대신을 사용하십시오 $routeProvider.
TRiNE

61

나는 똑같이하려고 노력했다. 동료와 작업 한 후 더 간단한 다른 솔루션을 찾았습니다. 에 시계가 설치되어 있습니다 $location.path(). 그 트릭을 수행합니다. 방금 AngularJS를 배우기 시작했으며 더 깨끗하고 읽기 쉽습니다.

$scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
    if ($scope.loggedIn == false && newValue != '/login'){  
            $location.path('/login');  
    }  
});

이것은 매우 흥미로운 것 같습니다. 어딘가에 예제를 게시 할 수 있었습니까?
kyleroche

3
시계는 어디에 설치합니까?
freakTheMighty

3
@freakTheMighty ng-controller가 mainCtrl로 설정된 mainCtrl 함수에서 시계를 설정해야합니다. 예 : <body ng-controller = "mainCtrl">
user1807337

5
부정적인 투표가 주어지면 이성에 대한 의견을 제시하는 것이 공정하다고 생각합니다. 학습 도구로 도움이 될 것입니다.
user1807337

37

로그인 리디렉션을 구현하는 다른 방법은 여기에 설명 된대로 이벤트와 인터셉터를 사용하는 입니다. 이 기사에서는 로그인이 필요한시기를 감지하고 요청을 큐에 넣은 후 로그인에 성공하면 다시 재생하는 등의 추가 이점에 대해 설명합니다.

여기서 실제 데모를 시도하고 여기 에서 데모 소스를 볼 수 있습니다 .


3
링크의 관련 정보를 포함하도록이 답변을 업데이트 할 수 있습니까? 그렇게하면 링크가 다운 되더라도 방문자에게 계속 유용 할 것입니다.
josliber

34

1. 글로벌 현재 사용자를 설정하십시오.

인증 서비스에서 현재 인증 된 사용자를 루트 범위에서 설정하십시오.

// AuthService.js

  // auth successful
  $rootScope.user = user

2. 보호 된 각 경로에 인증 기능을 설정하십시오.

// 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('/') }
    }
  })
})

또는 사용자 객체에 대한 권한을 설정하고 각 경로에 권한을 할당 한 다음 이벤트 콜백에서 권한을 확인할 수 있습니다.


@malcolmhall yup, 이것은 옵트 인이며 옵트 아웃하고 싶습니다. 대신 "public"부울을 로그인 페이지와 같은 공용 경로에 추가하고 경로 재 지정if (!user && !next.$$route.public)
AJcodez

누군가 next.$$route제게 설명해 주시겠습니까? Angular 문서에서 인수가 $routeChangeStart이벤트에 제공하는 것을 설명하는 것을 찾지 못했지만 일종의 위치 객체 라고 가정 next하고 curr있습니까? $$route비트는 구글 어렵다.
skagedal

2
$$route속성이 Angular의 개인 변수 라는 것을 알았습니다 . : 당신은 예를 들어보고, 그것에 의존해서는 안 stackoverflow.com/a/19338518/1132101 - 당신이 할 경우, 당신의 코드는 각도 변경을 깰 수 있습니다.
skagedal

2
개인 속성에 액세스하지 않고 경로를 액세스하거나 $route.routes목록 을 작성 하기 위해 반복 해야하는 방법을 찾았습니다 (@ thataustin 's answer에서와 같이) : 위치의 경로를 가져 와서 next.originalPath색인에 사용하십시오 $route.routes: var auth = $route.routes[next.originalPath].
skagedal

이벤트에 주어진 인수에 대해 3 개의 의견에서 내 질문에 대답하려면 실제로 문서화되지 않은 것 같습니다.이 문제를 참조하십시오.이 문제는 github.com/angular/angular.js/issues/ 10994
skagedal

27

누군가를 도울 수 있도록 내가 한 방법은 다음과 같습니다.

구성 publicAccess에서 공개 또는 공개하려는 몇 가지 경로에 속성을 설정했습니다 (로그인 또는 등록)

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

그런 다음 실행 블록 에서 사용자에게 액세스 권한이 없거나 경로에 공개적으로 액세스 할 수없는 경우 $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다른 것으로 바꿀 수 있습니다 ... 다른 방법을 보여주는 것입니다.


그리고 런 블록 인수의 사용자는 무엇입니까? 서비스?
mohamnag

예, 쿠키 등을 확인하여 사용자가 로그인했는지 확인하는 서비스입니다.
thataustin

nextLoc.$$route.publicAccessbtw 와 같은 경로에 액세스 할 수 있습니다 .
AJcodez

또는 $route.routes[nextLoc.originalPath]개인 변수를 사용하지 않는을 사용하십시오.
skagedal

1
실제로, 당신은 단지 확인할 수 있습니다 nextLoc && nextLoc.publicAccess!
skagedal

9

인터셉터를 사용하여하고 있습니다. index.html 파일에 추가 할 수있는 라이브러리 파일을 만들었습니다. 이렇게하면 나머지 서비스 요청에 대한 전역 오류 처리가 가능하며 모든 오류를 개별적으로 처리 할 필요는 없습니다. 또한 기본 인증 로그인 라이브러리를 붙여 넣었습니다. 거기에서 401 오류를 확인하고 다른 위치로 리디렉션하는 것을 볼 수 있습니다. lib / ea-basic-auth-login.js 참조

lib / http-error-handling.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;
}

index.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>

lib / ea-basic-auth-login.js

로그인에 대해 거의 동일하게 수행 할 수 있습니다. 여기에 리디렉션에 대한 답변이 있습니다 ($ location.path ( "/ login")).

/**
* @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;
            }
        };
    });
})();

2
지시어가 아닌 한 JS에서 DOM 조작을 멀리해야합니다. 방금 논리를 설정 한 다음 ng-class를 사용하여 클래스를 적용하고 CSS 애니메이션을 트리거하는 경우 나중에 감사하겠습니다.
Askdesigners

7

app.js 파일에서 :

.run(["$rootScope", "$state", function($rootScope, $state) {

      $rootScope.$on('$locationChangeStart', function(event, next, current) {
        if (!$rootScope.loggedUser == null) {
          $state.go('home');
        }    
      });
}])

4

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>

3

angular-ui-router를 사용하고 싶지 않지만 RequireJS를 통해 컨트롤러를 지연로드하려면 $routeChangeStart컨트롤러를 RequireJS 모듈 (게으른로드)로 사용할 때 이벤트에 몇 가지 문제가 있습니다.

$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
    });
}]);

즉, 액세스 권한을 확인할 수 없습니다.

해결책:

컨트롤러로드는 resolve를 통해 수행되므로 액세스 제어 검사와 동일하게 수행 할 수 있습니다.

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"
    });
}]);

여기서 이벤트를 사용하는 대신 $routeChangeStart사용하고 있습니다.$routeChangeError


-4
    $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'});

이것은 기본 경로 구성입니다 ... 구성된 경로로 리디렉션하기 전에 조건을 어디에서 확인합니까?
TJ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.