Về cơ bản, tôi đã tạo một repo github tóm tắt bài viết này: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-application-7bbf0346acec
ng-login Github repo
Plunker
Tôi sẽ cố gắng giải thích tốt nhất có thể, hy vọng tôi sẽ giúp một số bạn ở đó:
(1) app.js: Tạo hằng số xác thực trên định nghĩa ứng dụng
var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
all : '*',
admin : 'admin',
editor : 'editor',
guest : 'guest'
}).constant('AUTH_EVENTS', {
loginSuccess : 'auth-login-success',
loginFailed : 'auth-login-failed',
logoutSuccess : 'auth-logout-success',
sessionTimeout : 'auth-session-timeout',
notAuthenticated : 'auth-not-authenticated',
notAuthorized : 'auth-not-authorized'
})
(2) Dịch vụ xác thực: Tất cả các chức năng sau được triển khai trong dịch vụ auth.js. Dịch vụ $ http được sử dụng để giao tiếp với máy chủ cho các thủ tục xác thực. Cũng chứa các chức năng về ủy quyền, đó là nếu người dùng được phép thực hiện một hành động nhất định.
angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS',
function($http, $rootScope, $window, Session, AUTH_EVENTS) {
authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]
return authService;
} ]);
(3) Phiên: Một singleton để giữ dữ liệu người dùng. Việc thực hiện ở đây phụ thuộc vào bạn.
angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {
this.create = function(user) {
this.user = user;
this.userRole = user.userRole;
};
this.destroy = function() {
this.user = null;
this.userRole = null;
};
return this;
});
(4) Bộ điều khiển chính: Coi đây là chức năng "chính" của ứng dụng của bạn, tất cả các bộ điều khiển kế thừa từ bộ điều khiển này và nó là xương sống của việc xác thực ứng dụng này.
<body ng-controller="ParentController">
[...]
</body>
(5) Kiểm soát truy cập: Để từ chối truy cập trên các tuyến đường nhất định, bạn phải thực hiện 2 bước:
a) Thêm dữ liệu của các vai trò được phép truy cập từng tuyến, trên dịch vụ $ stateProvider của bộ định tuyến ui như có thể thấy bên dưới (tương tự có thể hoạt động cho ngRoute).
.config(function ($stateProvider, USER_ROLES) {
$stateProvider.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
data: {
authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
}
});
})
b) Trên $ rootScope. $ on ('$ stateChangeStart') thêm chức năng để ngăn thay đổi trạng thái nếu người dùng không được phép.
$rootScope.$on('$stateChangeStart', function (event, next) {
var authorizedRoles = next.data.authorizedRoles;
if (!Auth.isAuthorized(authorizedRoles)) {
event.preventDefault();
if (Auth.isAuthenticated()) {
// user is not allowed
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
} else {
// user is not logged in
$rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
}
}
});
(6) Bộ đánh chặn xác thực: Điều này được triển khai, nhưng không thể kiểm tra trên phạm vi của mã này. Sau mỗi yêu cầu $ http, bộ chặn này sẽ kiểm tra mã trạng thái, nếu một trong các mã dưới đây được trả về, thì nó sẽ phát ra một sự kiện để buộc người dùng đăng nhập lại.
angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
return {
responseError : function(response) {
$rootScope.$broadcast({
401 : AUTH_EVENTS.notAuthenticated,
403 : AUTH_EVENTS.notAuthorized,
419 : AUTH_EVENTS.sessionTimeout,
440 : AUTH_EVENTS.sessionTimeout
}[response.status], response);
return $q.reject(response);
}
};
} ]);
PS Có thể dễ dàng tránh được lỗi với tính năng tự động điền dữ liệu biểu mẫu như đã nêu trong bài viết đầu tiên bằng cách thêm chỉ thị được bao gồm trong chỉ thị .js.
PS2 Người dùng có thể dễ dàng tinh chỉnh mã này, để cho phép các tuyến đường khác nhau được nhìn thấy, hoặc hiển thị nội dung không được phép hiển thị. Logic PHẢI được triển khai phía máy chủ, đây chỉ là một cách để hiển thị mọi thứ đúng cách trên ng-app của bạn.