为了账号安全,请及时绑定邮箱和手机立即绑定

AngularJS-每个路由和控制器中的登录和身份验证

AngularJS-每个路由和控制器中的登录和身份验证

冉冉说 2019-07-23 16:31:57
AngularJS-每个路由和控制器中的登录和身份验证我有一个使用yeoman,grunt和bower创建的AngularJS应用程序。我有一个登录页面,其中包含一个检查身份验证的控制器。如果凭据正确,我将重新路由到主页。app.js'use strict';//Define Routing for appangular.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";         }     }});在loginController,我检查登录信息,如果成功,我在服务工厂设置用户对象。我不知道这是否正确。我需要的是,当用户登录时,它在用户对象中设置一些值,以便所有其他页面都可以获得该值。无论何时发生任何路由更改,控制器都应检查用户是否已登录。如果没有,它应该重新路由到登录页面。此外,如果用户已登录并返回页面,则应转到主页。控制器还应检查所有路由上的凭据。我听说过ng-cookies,但我不知道如何使用它们。我看到的许多例子都不是很清楚,他们使用某种访问角色或其他东西。我不希望这样。我只想要一个登录过滤器。有人可以给我一些想法吗?
查看完整描述

3 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

这是另一种可能的解决方案,使用或的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");
    });
  };}])


查看完整回答
反对 回复 2019-07-23
?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

为各个路由定义自定义行为的最简单方法相当简单:

1)routes.jsrequireAuth为任何所需的路线创建一个新属性(如)

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


查看完整回答
反对 回复 2019-07-23
  • 3 回答
  • 0 关注
  • 852 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信