AngularJS- เข้าสู่ระบบและรับรองความถูกต้องในแต่ละเส้นทางและตัวควบคุม


130

ฉันมีแอปพลิเคชั่น AngularJS ที่สร้างขึ้นโดยใช้ Yeoman, Grunt และ Bower

ฉันมีหน้าล็อกอินที่มีคอนโทรลเลอร์ที่ตรวจสอบการพิสูจน์ตัวตน ถ้าข้อมูลรับรองถูกต้องฉันเปลี่ยนเส้นทางไปที่โฮมเพจ

app.js

'use strict';
//Define Routing for app
angular.module('myApp', []).config(['$routeProvider', '$locationProvider',
  function($routeProvider,$locationProvider) {
    $routeProvider
    .when('/login', {
        templateUrl: 'login.html',
        controller: 'LoginController'
    })
    .when('/register', {
        templateUrl: 'register.html',
        controller: 'RegisterController'
      })
    .when('/forgotPassword', {
        templateUrl: 'forgotpassword.html',
        controller: 'forgotController'
      })
   .when('/home', {
       templateUrl: 'views/home.html',
       controller: 'homeController'
    })
    .otherwise({
       redirectTo: '/login'
    });
//    $locationProvider.html5Mode(true); //Remove the '#' from URL.
}]);

angular.module('myApp').factory("page", function($rootScope){
    var page={};
    var user={};
    page.setPage=function(title,bodyClass){
        $rootScope.pageTitle = title;
        $rootScope.bodylayout=bodyClass;
    };
    page.setUser=function(user){
        $rootScope.user=user;
    }
    return page;
});

LoginControler.js

'use strict';

angular.module('myApp').controller('LoginController', function($scope, $location, $window,page) {
    page.setPage("Login","login-layout");
    $scope.user = {};
    $scope.loginUser=function()
    {
        var username=$scope.user.name;
        var password=$scope.user.password;
        if(username=="admin" && password=="admin123")
        {
            page.setUser($scope.user);
            $location.path( "/home" );
        }
        else
        {
            $scope.message="Error";
            $scope.messagecolor="alert alert-danger";
        }
    }
});

ในหน้าแรกฉันมี

<span class="user-info">
    <small>Welcome,</small>
    {{user.name}}
</span>
<span class="logout"><a href="" ng-click="logoutUser()">Logout</a></span>

ใน loginControllerตรวจสอบข้อมูลการเข้าสู่ระบบและหากสำเร็จฉันจะตั้งค่าวัตถุผู้ใช้ในโรงงานบริการ ผมไม่รู้ว่าถูกต้องหรือไม่

สิ่งที่ฉันต้องการคือเมื่อผู้ใช้เข้าสู่ระบบมันจะตั้งค่าบางอย่างในออบเจ็กต์ผู้ใช้เพื่อให้เพจอื่น ๆ ทั้งหมดสามารถรับค่านั้นได้

เมื่อใดก็ตามที่เกิดการเปลี่ยนแปลงเส้นทางผู้ควบคุมควรตรวจสอบว่าผู้ใช้เข้าสู่ระบบหรือไม่ หากไม่เป็นเช่นนั้นควรเปลี่ยนเส้นทางไปที่หน้าเข้าสู่ระบบ นอกจากนี้หากผู้ใช้เข้าสู่ระบบแล้วและกลับมาที่หน้านั้นควรไปที่โฮมเพจ ผู้ควบคุมควรตรวจสอบข้อมูลประจำตัวในทุกเส้นทางด้วย

ฉันเคยได้ยินเกี่ยวกับ ng-cookies แต่ฉันไม่รู้วิธีใช้

หลายตัวอย่างที่ฉันเห็นไม่ชัดเจนนักและใช้บทบาทการเข้าถึงบางอย่างหรือบางอย่าง ฉันไม่ต้องการสิ่งนั้น ฉันต้องการตัวกรองการเข้าสู่ระบบเท่านั้น ใครช่วยให้ความคิดฉันบ้าง

คำตอบ:


180

โซลูชันของฉันแบ่งออกเป็น 3 ส่วน: สถานะของผู้ใช้จะถูกเก็บไว้ในบริการในวิธีการเรียกใช้ที่คุณดูเมื่อเส้นทางเปลี่ยนไปและคุณตรวจสอบว่าผู้ใช้ได้รับอนุญาตให้เข้าถึงหน้าที่ร้องขอหรือไม่ในตัวควบคุมหลักของคุณที่คุณดูถ้า สถานะของผู้ใช้เปลี่ยนไป

app.run(['$rootScope', '$location', 'Auth', function ($rootScope, $location, Auth) {
    $rootScope.$on('$routeChangeStart', function (event) {

        if (!Auth.isLoggedIn()) {
            console.log('DENY');
            event.preventDefault();
            $location.path('/login');
        }
        else {
            console.log('ALLOW');
            $location.path('/home');
        }
    });
}]);

คุณควรสร้างบริการ (ฉันจะตั้งชื่อAuth) ซึ่งจะจัดการกับวัตถุผู้ใช้และมีวิธีการที่จะทราบว่าผู้ใช้เข้าสู่ระบบหรือไม่

บริการ :

 .factory('Auth', function(){
var user;

return{
    setUser : function(aUser){
        user = aUser;
    },
    isLoggedIn : function(){
        return(user)? user : false;
    }
  }
})

จากของapp.runคุณคุณควรฟัง$routeChangeStartเหตุการณ์ เมื่อเส้นทางจะเปลี่ยนมันจะตรวจสอบว่าผู้ใช้เข้าสู่ระบบหรือไม่ (ไฟล์isLoggedInวิธีนี้ควรจัดการ) จะไม่โหลดเส้นทางที่ร้องขอหากผู้ใช้ไม่ได้เข้าสู่ระบบและจะเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าที่ถูกต้อง (ในกรณีของคุณเข้าสู่ระบบ)

loginControllerควรจะใช้ในหน้าเข้าสู่ระบบของคุณเพื่อเข้าสู่ระบบการจัดการ ควรขัดจังหวะAuthบริการและตั้งค่าผู้ใช้ว่าเข้าสู่ระบบหรือไม่

เข้าสู่ระบบคอนโทรลเลอร์ :

.controller('loginCtrl', [ '$scope', 'Auth', function ($scope, Auth) {
  //submit
  $scope.login = function () {
    // Ask to the server, do your job and THEN set the user

    Auth.setUser(user); //Update the state of the user in the app
  };
}])

จากตัวควบคุมหลักของคุณคุณสามารถฟังได้หากสถานะของผู้ใช้เปลี่ยนไปและตอบสนองด้วยการเปลี่ยนเส้นทาง

.controller('mainCtrl', ['$scope', 'Auth', '$location', function ($scope, Auth, $location) {

  $scope.$watch(Auth.isLoggedIn, function (value, oldValue) {

    if(!value && oldValue) {
      console.log("Disconnect");
      $location.path('/login');
    }

    if(value) {
      console.log("Connect");
      //Do something when the user is connected
    }

  }, true);

1
loginController จะอนุญาตให้ผู้ใช้ล็อกอินจากหน้าล็อกอิน มันจะจัดการกับแบบฟอร์มการเข้าสู่ระบบ แบบฟอร์มต้องเรียกใช้วิธีการส่งซึ่งเป็นส่วนหนึ่งของ loginController ของคุณ วิธีนี้จะอัปเดต (หากแบบฟอร์มถูกต้องและผู้ใช้ต้องเข้าสู่ระบบ) สถานะของผู้ใช้ที่ใช้บริการ Auth ที่ฉันอธิบายไว้
gab

2
ทำงานอย่างมีเสน่ห์! แทนการให้บริการที่ผมใช้Auth0 กับ AngularJS
Nikos Baxevanis

34
จะเกิดอะไรขึ้นถ้าผู้ใช้กด F5 และรีเฟรช? จากนั้นการตรวจสอบสิทธิ์ในหน่วยความจำของคุณจะหายไป
Gaui

4
ในกรณีที่ผู้อื่นมีปัญหาในการเรียกใช้ตัวอย่างนี้: ในการrouteChangeStartโทรกลับคุณควรตรวจสอบว่าตำแหน่งนั้นเป็น "/ ล็อกอิน" จริงหรือไม่และอนุญาตให้ใช้:if ( $location.path() === "/login" ) return;
user2084865

1
มันทำให้ฉันวนเวียนไม่สิ้นสุด
Nipun Tyagi

110

นี่เป็นอีกวิธีหนึ่งที่เป็นไปได้โดยใช้resolveแอตทริบิวต์ของ$stateProviderหรือ$routeProvider. ตัวอย่างด้วย$stateProvider:

.config(["$stateProvider", function ($stateProvider) {

  $stateProvider

  .state("forbidden", {
    /* ... */
  })

  .state("signIn", {
    /* ... */
    resolve: {
      access: ["Access", function (Access) { return Access.isAnonymous(); }],
    }
  })

  .state("home", {
    /* ... */
    resolve: {
      access: ["Access", function (Access) { return Access.isAuthenticated(); }],
    }
  })

  .state("admin", {
    /* ... */
    resolve: {
      access: ["Access", function (Access) { return Access.hasRole("ROLE_ADMIN"); }],
    }
  });

}])

Access แก้ไขหรือปฏิเสธสัญญาขึ้นอยู่กับสิทธิ์ของผู้ใช้ปัจจุบัน:

.factory("Access", ["$q", "UserProfile", function ($q, UserProfile) {

  var Access = {

    OK: 200,

    // "we don't know who you are, so we can't say if you're authorized to access
    // this resource or not yet, please sign in first"
    UNAUTHORIZED: 401,

    // "we know who you are, and your profile does not allow you to access this resource"
    FORBIDDEN: 403,

    hasRole: function (role) {
      return UserProfile.then(function (userProfile) {
        if (userProfile.$hasRole(role)) {
          return Access.OK;
        } else if (userProfile.$isAnonymous()) {
          return $q.reject(Access.UNAUTHORIZED);
        } else {
          return $q.reject(Access.FORBIDDEN);
        }
      });
    },

    hasAnyRole: function (roles) {
      return UserProfile.then(function (userProfile) {
        if (userProfile.$hasAnyRole(roles)) {
          return Access.OK;
        } else if (userProfile.$isAnonymous()) {
          return $q.reject(Access.UNAUTHORIZED);
        } else {
          return $q.reject(Access.FORBIDDEN);
        }
      });
    },

    isAnonymous: function () {
      return UserProfile.then(function (userProfile) {
        if (userProfile.$isAnonymous()) {
          return Access.OK;
        } else {
          return $q.reject(Access.FORBIDDEN);
        }
      });
    },

    isAuthenticated: function () {
      return UserProfile.then(function (userProfile) {
        if (userProfile.$isAuthenticated()) {
          return Access.OK;
        } else {
          return $q.reject(Access.UNAUTHORIZED);
        }
      });
    }

  };

  return Access;

}])

UserProfileสำเนาคุณสมบัติที่ผู้ใช้ปัจจุบันและดำเนินการ$hasRole, $hasAnyRole, $isAnonymousและ$isAuthenticatedวิธีการตรรกะ (บวก$refreshวิธีการอธิบายในภายหลัง):

.factory("UserProfile", ["Auth", function (Auth) {

  var userProfile = {};

  var clearUserProfile = function () {
    for (var prop in userProfile) {
      if (userProfile.hasOwnProperty(prop)) {
        delete userProfile[prop];
      }
    }
  };

  var fetchUserProfile = function () {
    return Auth.getProfile().then(function (response) {
      clearUserProfile();
      return angular.extend(userProfile, response.data, {

        $refresh: fetchUserProfile,

        $hasRole: function (role) {
          return userProfile.roles.indexOf(role) >= 0;
        },

        $hasAnyRole: function (roles) {
          return !!userProfile.roles.filter(function (role) {
            return roles.indexOf(role) >= 0;
          }).length;
        },

        $isAnonymous: function () {
          return userProfile.anonymous;
        },

        $isAuthenticated: function () {
          return !userProfile.anonymous;
        }

      });
    });
  };

  return fetchUserProfile();

}])

Auth รับผิดชอบในการร้องขอเซิร์ฟเวอร์เพื่อทราบโปรไฟล์ผู้ใช้ (เชื่อมโยงกับโทเค็นการเข้าถึงที่แนบมากับคำขอเป็นต้น):

.service("Auth", ["$http", function ($http) {

  this.getProfile = function () {
    return $http.get("api/auth");
  };

}])

เซิร์ฟเวอร์คาดว่าจะส่งคืนอ็อบเจ็กต์ JSON ดังกล่าวเมื่อร้องขอGET api/auth:

{
  "name": "John Doe", // plus any other user information
  "roles": ["ROLE_ADMIN", "ROLE_USER"], // or any other role (or no role at all, i.e. an empty array)
  "anonymous": false // or true
}

สุดท้ายเมื่อAccessปฏิเสธสัญญาถ้าใช้ui.routerใน$stateChangeErrorกรณีที่จะถูกไล่ออก:

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

  $rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
    switch (error) {

    case Access.UNAUTHORIZED:
      $state.go("signIn");
      break;

    case Access.FORBIDDEN:
      $state.go("forbidden");
      break;

    default:
      $log.warn("$stateChangeError event catched");
      break;

    }
  });

}])

ถ้าใช้ngRouteใน$routeChangeErrorกรณีที่จะถูกไล่ออก:

.run(["$rootScope", "Access", "$location", "$log", function ($rootScope, Access, $location, $log) {

  $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
    switch (rejection) {

    case Access.UNAUTHORIZED:
      $location.path("/signin");
      break;

    case Access.FORBIDDEN:
      $location.path("/forbidden");
      break;

    default:
      $log.warn("$stateChangeError event catched");
      break;

    }
  });

}])

โปรไฟล์ผู้ใช้ยังสามารถเข้าถึงได้ในคอนโทรลเลอร์:

.state("home", {
  /* ... */
  controller: "HomeController",
  resolve: {
    userProfile: "UserProfile"
  }
})

UserProfileจากนั้นจะมีคุณสมบัติที่ส่งคืนโดยเซิร์ฟเวอร์เมื่อร้องขอGET api/auth:

.controller("HomeController", ["$scope", "userProfile", function ($scope, userProfile) {

  $scope.title = "Hello " + userProfile.name; // "Hello John Doe" in the example

}])

UserProfileจะต้องมีการรีเฟรชเมื่อผู้ใช้ลงชื่อเข้าหรือออกเพื่อให้Accessสามารถจัดการเส้นทางด้วยโปรไฟล์ผู้ใช้ใหม่ได้ UserProfile.$refresh()คุณสามารถโหลดทั้งหน้าหรือโทร ตัวอย่างเมื่อลงชื่อเข้าใช้:

.service("Auth", ["$http", function ($http) {

  /* ... */

  this.signIn = function (credentials) {
    return $http.post("api/auth", credentials).then(function (response) {
      // authentication succeeded, store the response access token somewhere (if any)
    });
  };

}])
.state("signIn", {
  /* ... */
  controller: "SignInController",
  resolve: {
    /* ... */
    userProfile: "UserProfile"
  }
})
.controller("SignInController", ["$scope", "$state", "Auth", "userProfile", function ($scope, $state, Auth, userProfile) {

  $scope.signIn = function () {
    Auth.signIn($scope.credentials).then(function () {
      // user successfully authenticated, refresh UserProfile
      return userProfile.$refresh();
    }).then(function () {
      // UserProfile is refreshed, redirect user somewhere
      $state.go("home");
    });
  };

}])

3
ฉันคิดว่านี่เป็นคำตอบที่ง่ายที่สุดและสามารถขยายได้มากที่สุด
Jotham

2
@LeblancMeneses ขอบคุณ :) เพื่อให้ชัดเจนขึ้น: UNAUTHORIZED หมายความว่า"เราไม่รู้ว่าคุณเป็นใครดังนั้นเราจึงไม่สามารถบอกได้ว่าคุณได้รับอนุญาตให้เข้าถึงทรัพยากรนี้หรือยังโปรดลงชื่อเข้าใช้ก่อน"ในขณะที่ FORBIDDEN หมายถึง"เรารู้ว่าคุณเป็นใครและโปรไฟล์ของคุณไม่อนุญาตให้คุณสามารถเข้าถึงทรัพยากรนี้"
sp00m

1
วิธีแก้ปัญหาที่ดีเหมาะสมกับการรับรองความถูกต้องของ Spring บนฝั่งเซิร์ฟเวอร์
ม.ค. ปีเตอร์

1
ทางออกที่ดีที่สุดที่เคยมีมา!
Renan Franca

1
@jsbisht ทุกอย่างขึ้นอยู่กับว่าคุณจัดเก็บโทเค็นการเข้าถึงไว้ที่ใด (ดูตัวอย่างสุดท้าย) หากคุณเพียงเก็บไว้ในหน่วยความจำ JS แล้วใช่: F5 จะลบข้อมูลรับรองความถูกต้อง แต่ถ้าคุณเก็บไว้ในที่เก็บข้อมูลถาวร (เช่นคุกกี้ / localStorage / sessionStorage) ไม่: F5 จะไม่ลบข้อมูลการตรวจสอบสิทธิ์ (ตราบใดที่คุณแนบโทเค็นกับคำขอ $ http ทุกครั้งหรืออย่างน้อยก็กับคำขอที่ส่งไปยัง ส่วนที่เหลือ / ผู้ใช้ / โปรไฟล์เนื่องจากเซิร์ฟเวอร์คาดว่าจะส่งคืนโปรไฟล์ของผู้ใช้ที่เชื่อมโยงกับโทเค็นที่แนบมา) ระวัง CSRF เมื่อใช้ที่เก็บคุกกี้
sp00m

21

วิธีที่ง่ายที่สุดในการกำหนดพฤติกรรมที่กำหนดเองสำหรับแต่ละเส้นทางจะค่อนข้างง่าย:

1) routes.js: สร้างคุณสมบัติใหม่ (เช่นrequireAuth) สำหรับเส้นทางที่ต้องการ

angular.module('yourApp').config(function($routeProvider) {
    $routeProvider
        .when('/home', {
            templateUrl: 'templates/home.html',
            requireAuth: true // our custom property
        })
        .when('/login', {
            templateUrl: 'templates/login.html',
        })
        .otherwise({
            redirectTo: '/home'
        });
})

2) ในคอนโทรลเลอร์ระดับบนสุดที่ไม่ถูกผูกไว้กับองค์ประกอบภายในng-view(เพื่อหลีกเลี่ยงความขัดแย้งกับเชิงมุม$routeProvider) ให้ตรวจสอบว่าnewUrlมีrequireAuthคุณสมบัติหรือไม่และปฏิบัติตาม

 angular.module('YourApp').controller('YourController', function ($scope, $location, session) {

     // intercept the route change event
     $scope.$on('$routeChangeStart', function (angularEvent, newUrl) {

         // check if the custom property exist
         if (newUrl.requireAuth && !session.user) {

             // user isn’t authenticated
             $location.path("/login");
         }
     });
 });

1
เราสามารถระบุแอตทริบิวต์ "requireAuth: true" ให้กับเส้นทางทั้งหมดในที่เดียวได้หรือไม่? เนื่องจากในสถานการณ์ของฉันหน้านี้ไม่ใช่หน้าเข้าสู่ระบบ แต่ได้รับการรับรองความถูกต้องจากบุคคลที่สาม ดังนั้นฉันต้องการระบุในที่เดียวและควรใช้สำหรับเส้นทางที่เพิ่มในอนาคตด้วย
Raghuveer

1
ไม่ใช่ว่าฉันรู้ บางทีคุณอาจจะสามารถตรวจสอบได้ทุกroutes.jsเส้นทางที่ไม่ได้มีคุณสมบัติพิเศษที่กำหนดไว้ใน
DotBot

1
ตัวอย่างที่ดีและเรียบง่ายมันมีประโยชน์มากสำหรับความต้องการของฉัน
error505

6

ฉันเขียนโพสต์ไม่กี่เดือนย้อนหลังเกี่ยวกับวิธีตั้งค่าการลงทะเบียนผู้ใช้และฟังก์ชันการเข้าสู่ระบบด้วย Angular คุณสามารถตรวจสอบได้ที่http://jasonwatmore.com/post/2015/03/10/AngularJS-User-Registration-and -Login-Example.aspx

ฉันตรวจสอบว่าผู้ใช้เข้าสู่ระบบ$locationChangeStartเหตุการณ์หรือไม่นี่คือ app.js หลักของฉันที่แสดงสิ่งนี้:

(function () {
    'use strict';
 
    angular
        .module('app', ['ngRoute', 'ngCookies'])
        .config(config)
        .run(run);
 
    config.$inject = ['$routeProvider', '$locationProvider'];
    function config($routeProvider, $locationProvider) {
        $routeProvider
            .when('/', {
                controller: 'HomeController',
                templateUrl: 'home/home.view.html',
                controllerAs: 'vm'
            })
 
            .when('/login', {
                controller: 'LoginController',
                templateUrl: 'login/login.view.html',
                controllerAs: 'vm'
            })
 
            .when('/register', {
                controller: 'RegisterController',
                templateUrl: 'register/register.view.html',
                controllerAs: 'vm'
            })
 
            .otherwise({ redirectTo: '/login' });
    }
 
    run.$inject = ['$rootScope', '$location', '$cookieStore', '$http'];
    function run($rootScope, $location, $cookieStore, $http) {
        // keep user logged in after page refresh
        $rootScope.globals = $cookieStore.get('globals') || {};
        if ($rootScope.globals.currentUser) {
            $http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line
        }
 
        $rootScope.$on('$locationChangeStart', function (event, next, current) {
            // redirect to login page if not logged in and trying to access a restricted page
            var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
            var loggedIn = $rootScope.globals.currentUser;
            if (restrictedPage && !loggedIn) {
                $location.path('/login');
            }
        });
    }
 
})();

เขียนได้ดี ฉันใช้มันเพื่อการอ้างอิง ขอบคุณ @Jason.
Venkat Kotra

2

ฉันรู้สึกว่าวิธีนี้ง่ายที่สุด แต่อาจเป็นเพียงความชอบส่วนตัว

เมื่อคุณระบุเส้นทางการเข้าสู่ระบบของคุณ (และเส้นทางอื่น ๆ ที่ไม่ระบุตัวตนเช่น: / register, / logout, / refreshToken ฯลฯ ) ให้เพิ่ม:

allowAnonymous: true

ดังนั้นสิ่งนี้:

$stateProvider.state('login', {
    url: '/login',
    allowAnonymous: true, //if you move this, don't forget to update
                          //variable path in the force-page check.
    views: {
        root: {
            templateUrl: "app/auth/login/login.html",
            controller: 'LoginCtrl'
        }
    }
    //Any other config
}

คุณไม่จำเป็นต้องระบุ "allowAnonymous: false" หากไม่มีก็ถือว่าเป็นเท็จในการตรวจสอบ ในแอปที่บังคับให้ตรวจสอบสิทธิ์ URL ส่วนใหญ่จะใช้งานได้น้อยกว่า และปลอดภัยยิ่งขึ้น; หากคุณลืมเพิ่มลงใน URL ใหม่สิ่งที่เลวร้ายที่สุดที่อาจเกิดขึ้นคือ URL ที่ไม่ระบุตัวตนได้รับการปกป้อง หากคุณทำอีกวิธีหนึ่งโดยระบุว่า "requireAuthentication: true" และคุณลืมเพิ่มลงใน URL แสดงว่าคุณกำลังเผยแพร่เพจที่ละเอียดอ่อนสู่สาธารณะ

จากนั้นเรียกใช้ทุกที่ที่คุณรู้สึกว่าเหมาะกับการออกแบบโค้ดของคุณที่สุด

//I put it right after the main app module config. I.e. This thing:
angular.module('app', [ /* your dependencies*/ ])
       .config(function (/* you injections */) { /* your config */ })

//Make sure there's no ';' ending the previous line. We're chaining. (or just use a variable)
//
//Then force the logon page
.run(function ($rootScope, $state, $location, User /* My custom session obj */) {
    $rootScope.$on('$stateChangeStart', function(event, newState) {
        if (!User.authenticated && newState.allowAnonymous != true) {
            //Don't use: $state.go('login');
            //Apparently you can't set the $state while in a $state event.
            //It doesn't work properly. So we use the other way.
            $location.path("/login");
        }
    });
});

1

app.js

'use strict';
// Declare app level module which depends on filters, and services
var app= angular.module('myApp', ['ngRoute','angularUtils.directives.dirPagination','ngLoadingSpinner']);
app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/login', {templateUrl: 'partials/login.html', controller: 'loginCtrl'});
  $routeProvider.when('/home', {templateUrl: 'partials/home.html', controller: 'homeCtrl'});
  $routeProvider.when('/salesnew', {templateUrl: 'partials/salesnew.html', controller: 'salesnewCtrl'});
  $routeProvider.when('/salesview', {templateUrl: 'partials/salesview.html', controller: 'salesviewCtrl'});
  $routeProvider.when('/users', {templateUrl: 'partials/users.html', controller: 'usersCtrl'});
    $routeProvider.when('/forgot', {templateUrl: 'partials/forgot.html', controller: 'forgotCtrl'});


  $routeProvider.otherwise({redirectTo: '/login'});


}]);


app.run(function($rootScope, $location, loginService){
    var routespermission=['/home'];  //route that require login
    var salesnew=['/salesnew'];
    var salesview=['/salesview'];
    var users=['/users'];
    $rootScope.$on('$routeChangeStart', function(){
        if( routespermission.indexOf($location.path()) !=-1
        || salesview.indexOf($location.path()) !=-1
        || salesnew.indexOf($location.path()) !=-1
        || users.indexOf($location.path()) !=-1)
        {
            var connected=loginService.islogged();
            connected.then(function(msg){
                if(!msg.data)
                {
                    $location.path('/login');
                }

            });
        }
    });
});

loginServices.js

'use strict';
app.factory('loginService',function($http, $location, sessionService){
    return{
        login:function(data,scope){
            var $promise=$http.post('data/user.php',data); //send data to user.php
            $promise.then(function(msg){
                var uid=msg.data;
                if(uid){
                    scope.msgtxt='Correct information';
                    sessionService.set('uid',uid);
                    $location.path('/home');
                }          
                else  {
                    scope.msgtxt='incorrect information';
                    $location.path('/login');
                }                  
            });
        },
        logout:function(){
            sessionService.destroy('uid');
            $location.path('/login');
        },
        islogged:function(){
            var $checkSessionServer=$http.post('data/check_session.php');
            return $checkSessionServer;
            /*
            if(sessionService.get('user')) return true;
            else return false;
            */
        }
    }

});

sessionServices.js

'use strict';

app.factory('sessionService', ['$http', function($http){
    return{
        set:function(key,value){
            return sessionStorage.setItem(key,value);
        },
        get:function(key){
            return sessionStorage.getItem(key);
        },
        destroy:function(key){
            $http.post('data/destroy_session.php');
            return sessionStorage.removeItem(key);
        }
    };
}])

loginCtrl.js

'use strict';

app.controller('loginCtrl', ['$scope','loginService', function ($scope,loginService) {
    $scope.msgtxt='';
    $scope.login=function(data){
        loginService.login(data,$scope); //call login service
    };

}]);

1

คุณสามารถใช้resolve:

angular.module('app',[])
.config(function($routeProvider)
{
    $routeProvider
    .when('/', {
        templateUrl  : 'app/views/login.html',
        controller   : 'YourController',
        controllerAs : 'Your',
        resolve: {
            factory : checkLoginRedirect
        }
    })
}

และฟังก์ชั่นของการแก้ไข:

function checkLoginRedirect($location){

    var user = firebase.auth().currentUser;

    if (user) {
        // User is signed in.
        if ($location.path() == "/"){
            $location.path('dash'); 
        }

        return true;
    }else{
        // No user is signed in.
        $location.path('/');
        return false;
    }   
}

Firebase ยังมีวิธีการที่ช่วยให้คุณติดตั้งผู้สังเกตการณ์ฉันแนะนำให้ติดตั้งภายใน.run:

.run(function(){

    firebase.auth().onAuthStateChanged(function(user) {
        if (user) {
            console.log('User is signed in.');
        } else {
            console.log('No user is signed in.');
        }
    });
  }

0

ตัวอย่างเช่นแอปพลิเคชันมีผู้ใช้สองคนเรียกว่า ap และ auc ฉันกำลังส่งคุณสมบัติพิเศษไปยังแต่ละเส้นทางและจัดการการกำหนดเส้นทางตามข้อมูลที่ฉันได้รับใน $ routeChangeStart

ลองสิ่งนี้:

angular.module("app").config(['$routeProvider',
function ($routeProvider) {

    $routeProvider.
            when('/ap', {
                templateUrl: 'template1.html',
                controller: 'template1',
                isAp: 'ap',
            }).
            when('/auc', {
                templateUrl: 'template2.html',
                controller: 'template2',
                isAp: 'common',
            }).
            when('/ic', {
                templateUrl: 'template3.html',
                controller: 'template3',
                isAp: 'auc',
            }).
            when('/mup', {
                templateUrl: 'template4.html',
                controller: 'template4',
                isAp: 'ap',
            }).

            when('/mnu', {
                templateUrl: 'template5.html',
                controller: 'template5',
                isAp: 'common',
            }).                               
            otherwise({
                redirectTo: '/ap',
            });
   }]);

app.js:

.run(['$rootScope', '$location', function ($rootScope, $location) {                
    $rootScope.$on("$routeChangeStart", function (event, next, current) {
        if (next.$$route.isAp != 'common') {
            if ($rootScope.userTypeGlobal == 1) {
                if (next.$$route.isAp != 'ap') {
                    $location.path("/ap");
                }
            }
            else {
                if (next.$$route.isAp != 'auc') {
                    $location.path("/auc");
                }                        
            }
        }

    });
}]);

0

ทั้งหมดได้แนะนำวิธีแก้ปัญหาใหญ่ว่าทำไมคุณถึงกังวลกับเซสชันในฝั่งไคลเอ็นต์ ฉันหมายถึงเมื่อ state / url เปลี่ยนฉันคิดว่าคุณกำลังทำการเรียก ajax เพื่อโหลดข้อมูลสำหรับ tempelate

Note :- To Save user's data you may use `resolve` feature of `ui-router`.
 Check cookie if it exist load template , if even cookies doesn't exist than 
there is no chance of logged in , simply redirect to login template/page.

ตอนนี้ข้อมูล ajax ถูกส่งคืนโดยเซิร์ฟเวอร์โดยใช้ api ใด ๆ ตอนนี้จุดเริ่มต้นในการเล่นส่งคืนประเภทผลตอบแทนมาตรฐานโดยใช้เซิร์ฟเวอร์ตามสถานะการเข้าสู่ระบบของผู้ใช้ ตรวจสอบรหัสส่งคืนเหล่านั้นและดำเนินการตามคำขอของคุณในตัวควบคุม หมายเหตุ: - สำหรับคอนโทรลเลอร์ที่ไม่ต้องการการโทรแบบ ajax แบบเนทีฟคุณสามารถเรียกคำขอเปล่าไปยังเซิร์ฟเวอร์ได้เช่นนี้server.location/api/checkSession.phpและนี่คือcheckSession.php

<?php/ANY_LANGUAGE
session_start();//You may use your language specific function if required
if(isset($_SESSION["logged_in"])){
set_header("200 OK");//this is not right syntax , it is just to hint
}
else{
set_header("-1 NOT LOGGED_IN");//you may set any code but compare that same       
//code on client side to check if user is logged in or not.
}
//thanks.....

ในฝั่งไคลเอ็นต์ภายในคอนโทรลเลอร์หรือผ่านบริการใด ๆ ตามที่แสดงในคำตอบอื่น ๆ

    $http.get(dataUrl)
    .success(function (data){
        $scope.templateData = data;
    })
    .error(function (error, status){
        $scope.data.error = { message: error, status: status};
        console.log($scope.data.error.status);
if(status == CODE_CONFIGURED_ON_SERVER_SIDE_FOR_NON_LOGGED_IN){
//redirect to login
  });

หมายเหตุ: - ฉันจะอัปเดตเพิ่มเติมในวันพรุ่งนี้หรือในอนาคต


-1

คุณควรตรวจสอบการรับรองความถูกต้องของผู้ใช้ในสองไซต์หลัก

  • เมื่อผู้ใช้เปลี่ยนสถานะให้ตรวจสอบโดยใช้การ'$routeChangeStart'โทรกลับ
  • เมื่อคำขอ $ http ถูกส่งจากเชิงมุมโดยใช้ตัวสกัดกั้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.