การเปลี่ยนเส้นทางไปยังเส้นทางที่แน่นอนตามเงื่อนไข


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 เป็นโมฆะให้เปลี่ยนเส้นทางไปยัง / เข้าสู่ระบบ"

...

... รอ ฉันสามารถฟังการเปลี่ยนแปลงเส้นทางได้หรือไม่ ฉันจะโพสต์คำถามนี้ต่อไปและดูต่อไป


3
เพียงชี้แจง: ในขณะที่วิธีแก้ปัญหาด้านล่างทำงานได้ดีฉันเพิ่งมีแนวโน้มยอมรับคำตอบ @ Oran ด้านล่าง - กล่าวคือให้เซิร์ฟเวอร์ตอบสนองด้วยรหัส 401 เมื่อขอ URL ที่ละเอียดอ่อนและใช้ข้อมูลนั้นเพื่อควบคุม "กล่องเข้าสู่ระบบ" บนไคลเอนต์ (อย่างไรก็ตามคณะลูกขุนยังคงออกมาในบิต "คำขอเข้าคิวถูกปฏิเสธและออกใหม่ในภายหลัง" บิตอย่างน้อยสำหรับฉัน :))
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) เนื่องจากวัตถุเส้นทาง "ถัดไป" ไม่มี URL หรืออย่างอื่น อาจจะมีวิธีที่ดีกว่า


13
ผู้ชายเท่ขอบคุณสำหรับการแบ่งปันทางออกของคุณ สิ่งหนึ่งที่ควรทราบ: ในเวอร์ชันปัจจุบันมันคือ "next. $ route.templateUrl"
doubledriscoll

5
หากคุณดูคำขอเครือข่ายในตัวตรวจสอบ Chrome เส้นทางที่ถูกเปลี่ยนเส้นทาง (เนื่องจากผู้ใช้ไม่ได้ลงชื่อเข้าใช้) จะยังคงถูกเรียกใช้และการตอบกลับจะถูกส่งไปยังเบราว์เซอร์จากนั้นจะเรียกเส้นทาง '/ login' ที่เปลี่ยนเส้นทาง ดังนั้นวิธีนี้จึงไม่ดีเนื่องจากผู้ใช้ที่ไม่ได้ลงชื่อเข้าใช้สามารถเห็นการตอบสนองสำหรับเส้นทางที่พวกเขาไม่ควรเข้าถึง
sonicboom

34
ใช้ $ locationChangeStart แทน $ routeChangeStart เพื่อป้องกันเส้นทางจากการถูกเรียกใช้และอนุญาตให้ผู้ใช้ที่ไม่ได้ตรวจสอบสิทธิ์ดูเนื้อหาที่ไม่ควรมีการเข้าถึง
sonicboom

17
จำไว้ว่านี่คือไคลเอนต์ ควรมีสิ่งกีดขวางฝั่งเซิร์ฟเวอร์
Neikos

2
@sonicboom $ locationChangeStart ไม่สมเหตุสมผลถ้าไม่ใช่ทุกเส้นทางที่ต้องการการรับรองความถูกต้องด้วย $ routeChangeStart คุณสามารถมีข้อมูลเมตาบนวัตถุเส้นทางเช่นว่ามีการรับรองความถูกต้องหรือไม่หรือบทบาทนั้นจำเป็นต้องใช้สำหรับเส้นทางนั้น เซิร์ฟเวอร์ของคุณควรจัดการไม่แสดงเนื้อหาที่ไม่ได้รับการรับรองความถูกต้องและ AngularJS จะไม่เริ่มดำเนินการจนกว่าจะมีการเปลี่ยนแปลงเส้นทางดังนั้นจึงไม่ควรแสดงอะไร
Chris Nicola

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 เชิงมุม: "โรงงาน - {string | ฟังก์ชั่น}: ถ้าสตริงมันเป็นนามแฝงสำหรับบริการมิฉะนั้นถ้าฟังก์ชั่นแล้วมันจะถูกฉีดและค่าตอบแทนจะถือว่าเป็นการพึ่งพาถ้า ผลลัพธ์คือสัญญามันถูกแก้ไขก่อนที่ค่าจะถูกส่งเข้าไปในคอนโทรลเลอร์โปรดทราบว่า 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 คุณต้องตั้งค่านาฬิกาในฟังก์ชั่น mainCtrl ของคุณโดยที่ ng-controller ถูกตั้งค่าเป็น 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 นี่คือการเลือกใช้และคุณต้องการยกเลิก แทนที่จะเพิ่มบูลีน "สาธารณะ" ให้กับเส้นทางสาธารณะเช่นหน้าเข้าสู่ระบบและเปลี่ยนเส้นทางif (!user && !next.$$route.public)
AJcodez

มีคนช่วยอธิบายnext.$$routeให้ฉันหน่อยได้ไหม? ฉันไม่พบสิ่งใดใน Angular docs ที่อธิบายถึงข้อโต้แย้งที่ให้กับ$routeChangeStartเหตุการณ์ แต่ฉันถือว่าnextและcurrเป็นวัตถุตำแหน่งบางชนิด $$routeบิตยากที่จะ google
skagedal

2
ฉันเห็นแล้วว่า$$routeทรัพย์สินนี้เป็นตัวแปรส่วนตัวของแองกูลาร์ คุณไม่ควรพึ่งพาสิ่งนั้นดูตัวอย่าง: stackoverflow.com/a/19338518/1132101 - ถ้าคุณทำรหัสของคุณอาจแตกเมื่อการเปลี่ยนแปลงเชิงมุม
skagedal

2
ฉันได้พบวิธีที่จะเข้าถึงเส้นทางโดยไม่ต้องเข้าถึงทรัพย์สินส่วนตัวหรือมีการห่วงผ่าน$route.routesการสร้างรายการ (ในขณะที่คำตอบ @ thataustin ของ): ได้รับเส้นทางสำหรับสถานที่ที่มีnext.originalPathและการใช้งานที่จะจัดทำดัชนี:$route.routes var auth = $route.routes[next.originalPath]
skagedal

ในการตอบคำถามของฉันจากความคิดเห็นสามรายการที่ผ่านมาในข้อโต้แย้งที่ให้ไว้กับเหตุการณ์ - ดูเหมือนว่าพวกเขาจะไม่มีเอกสารจริงๆให้ดูปัญหานี้ซึ่งเกิดขึ้นกับการอ้างอิงคำถาม SO เช่นนี้: 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-ข้อผิดพลาด 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-ข้อผิดพลาด 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-พื้นฐานรับรองความถูกต้อง 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
คุณควรจะอยู่ห่างจากการทำ dom manipulation ใน JS อย่างแท้จริงเว้นแต่ว่าคุณจะได้รับคำสั่ง หากคุณเพิ่งตั้งค่าตรรกะของคุณแล้วใช้ ng-class เพื่อนำไปใช้ในชั้นเรียนและเรียกภาพเคลื่อนไหว CSS คุณจะขอบคุณตัวเองในภายหลัง
ออกแบบ Ask22

7

ในไฟล์ app.js ของคุณ:

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

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

4

มันเป็นไปได้ที่จะเปลี่ยนเส้นทางไปยังอีกมุมมองหนึ่งที่มีมุม-UI เตอร์ $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
    });
}]);

หมายความว่าคุณไม่สามารถตรวจสอบสิทธิ์การเข้าถึงได้

สารละลาย:

เมื่อโหลดตัวควบคุมเสร็จแล้วผ่านการแก้ไขคุณสามารถทำได้ด้วยการตรวจสอบการควบคุมการเข้าถึงของคุณ:

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.