当前位置: 首页 > 知识库问答 >
问题:

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

艾学海
2023-03-14

我有一个使用yeoman、grunt和bower创建的AngularJS应用程序。

我有一个登录页面,它有一个检查身份验证的控制器。如果凭据是正确的,我重新路由到主页。

应用程序。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;
});

登录ontroler.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中,我检查登录信息,如果成功,我在服务工厂中设置用户对象。我不知道这是否正确。

我需要的是,当用户登录时,它在user对象中设置一些值,以便所有其他页面都可以获得该值。

无论何时发生任何路由更改,控制器都应检查用户是否登录。如果没有,它应该重新路由到登录页面。此外,如果用户已经登录并返回页面,则应转到主页。控制器还应检查所有路由上的凭据。

我听说过ng-cookies,但我不知道如何使用它们。

我看到的许多例子都不是很清楚,它们使用某种访问角色或其他东西。我不想那样。我只想要一个登录过滤器。有人能给我一些想法吗?

共有3个答案

缪兴腾
2023-03-14

定义单个路由的自定义行为的最直接方式非常简单:

1)routes.js:为任何所需的路由创建一个新属性(如要求Auth

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是否具有要求的Auth属性,并相应地执行操作

 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");
         }
     });
 });
叶修永
2023-03-14

下面是另一种可能的解决方案,使用$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根据当前用户权限解析或拒绝promise:

.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$isAnnamous$isAuthentiated方法逻辑(加上一个$刷新方法,稍后解释):

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

}])

当请求GET api/auth时,服务器将返回这样的JSON对象:

{
  "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
}

最后,如果使用ui,当Access拒绝promise时。路由器,将触发$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.$刷新()。登录时的示例:

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

}])
汪丁雷
2023-03-14

我的解决方案分为三个部分:用户的状态存储在服务中,在路由更改时观察运行方法,检查用户是否允许访问请求的页面,在主控制器中观察用户的状态是否更改。

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);
 类似资料:
  • 我有一个使用yeoman、grunt和bower创建的AngularJS应用程序。 我有一个登录页面,它有一个检查身份验证的控制器。如果凭据是正确的,我重新路由到主页。 应用程序。js 登录ontroler.js 在我的主页上 在loginController中,我检查登录信息,如果成功,我在服务工厂中设置用户对象。我不知道这是否正确。 我需要的是,当用户登录时,它在user对象中设置一些值,以便

  • 问题内容: 我是AngularJS的新手,在以下情况下我对如何使用angular-“ ui-router”感到有些困惑: 我正在构建一个包含两个部分的Web应用程序。第一部分是带有登录和注册视图的主页,第二部分是仪表板(成功登录后)。 我为home部分创建了一个带有角度应用程序和配置的,用于处理和查看,还有一个针对仪表板部分的文件,其应用程序和配置用于处理许多子视图。 现在,我完成了仪表板部分,并

  • 我一直在搜索net,试图找到任何定义如何在流星和响应路由器4中处理身份验证的地方。 基本上,我希望某些路由只对经过身份验证的用户可用。有相关文件吗? 阿西尔

  • 问题内容: 我正在尝试建立一个视图-我设置了两个控制器进行练习,一个是HeaderCtrl,其中包含一些数据(网站标题,标题背景等),另一个应该具有页面的主要内容- MainCtrl。 在定义路线时,我这样做是: 这工作得很好,但是我想要为此指定多个参数,如下所示: 这行不通,所以我猜这不是做到这一点的方法。我实际上要问的是-您可以在$ routeProvider中指定多个控制器吗?还是构建此视图

  • 问题内容: 我正在开发Flask应用程序,并使用Flask-security进行用户身份验证(反过来又在下面使用Flask-login)。 我有一条需要身份验证的路由。我正在尝试编写一个单元测试,该测试对经过身份验证的用户返回适当的响应。 在单元测试中,我正在创建一个用户并以该用户身份登录,如下所示: 在测试内返回正确的用户。但是,请求的视图始终返回的。 所述路线定义为: 我可以肯定我只是不完全了

  • 我们正在尝试做一些具有登录屏幕的网站。但是我们有一个问题。我们的域是本地主机/登录/用户。但是,如果用户进入localhost/Home/Index,他/她无需登录即可访问我们的主站点。因此,我们将 [授权] 写入索引控制器。但我不知道我必须使用什么。我是否必须在我们的项目中使用AuthorizeAttribute? 如何访问LoginController/Authentication函数中的索引