신원 인증
가장 일반적인 신원 인증 방법은 사용자 이름(또는 이메일)과 비밀번호를 사용하여 로그인하는 것입니다. 이는 사용자가 자신의 개인 정보를 사용하여 로그인할 수 있도록 로그인 양식을 구현하는 것을 의미합니다. 양식은 다음과 같습니다.
<form name="loginForm" ng-controller="LoginController" ng-submit="login(credentials)" novalidate> <label for="username">Username:</label> <input type="text" id="username" ng-model="credentials.username"> <label for="password">Password:</label> <input type="password" id="password" ng-model="credentials.password"> <button type="submit">Login</button> </form>
이 양식은 Angular 기반 양식이므로 양식을 업로드할 때 ngSubmit 지시문을 사용하여 함수를 트리거합니다. 한 가지 주목할 점은 $scope.credentials 객체를 직접 사용하는 대신 업로드 양식 기능에 개인 정보를 전달한다는 것입니다. 이렇게 하면 함수의 단위 테스트가 더 쉬워지고 현재 컨트롤러 범위에 대한 함수의 결합이 줄어듭니다. 컨트롤러는 다음과 같습니다.
.controller('LoginController', function ($scope, $rootScope, AUTH_EVENTS, AuthService) { $scope.credentials = { username: '', password: '' }; $scope.login = function (credentials) { AuthService.login(credentials).then(function (user) { $rootScope.$broadcast(AUTH_EVENTS.loginSuccess); $scope.setCurrentUser(user); }, function () { $rootScope.$broadcast(AUTH_EVENTS.loginFailed); }); };javascript:void(0); })
여기에는 실제 논리가 부족하다는 것을 알았습니다. 이 컨트롤러는 양식에서 인증 논리를 분리하기 위해 이렇게 만들어졌습니다. 컨트롤러에서 가능한 한 많은 로직을 추출하여 모두 서비스에 넣는 것이 좋습니다. AngularJS의 컨트롤러는 지나치게 많은 작업을 수행하는 대신 $scope(관찰 또는 수동 작업을 사용하여)의 개체만 관리해야 합니다.
세션 변경 알림
신원 인증은 전체 애플리케이션 상태에 영향을 미칩니다. 이러한 이유로 나는 사용자 세션 변경 사항을 알리기 위해 이벤트($broadcast 사용)를 사용하는 것을 선호합니다. 가능한 모든 이벤트 코드를 중간 지점에서 정의하는 것이 좋습니다. 저는 이를 위해 상수를 사용하는 것을 좋아합니다.
.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' })
상수의 가장 큰 특징은 서비스와 마찬가지로 마음대로 다른 곳에 주입할 수 있다는 것입니다. 이를 통해 단위 테스트에서 상수를 쉽게 호출할 수 있습니다. 또한 상수를 사용하면 나중에 많은 파일을 변경하지 않고도 쉽게 이름을 바꿀 수 있습니다. 사용자 역할에도 동일한 방법이 적용됩니다.
.constant('USER_ROLES', { all: '*', admin: 'admin', editor: 'editor', guest: 'guest' })
편집자와 관리자에게 동일한 권한을 부여하려면 간단히 'editor'를 'admin'으로 변경하면 됩니다.
The AuthService
인증 및 권한 부여(액세스 제어)와 관련된 로직은 동일한 서비스에 배치하는 것이 가장 좋습니다.
.factory('AuthService', function ($http, Session) { var authService = {}; authService.login = function (credentials) { return $http .post('/login', credentials) .then(function (res) { Session.create(res.data.id, res.data.user.id, res.data.user.role); return res.data.user; }); }; authService.isAuthenticated = function () { return !!Session.userId; }; authService.isAuthorized = function (authorizedRoles) { if (!angular.isArray(authorizedRoles)) { authorizedRoles = [authorizedRoles]; } return (authService.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1); }; return authService; })
인증 걱정에서 벗어나기 위해 다른 서비스(싱글톤 객체, 다음을 사용)를 사용합니다. 서비스 스타일) 사용자의 세션 정보를 저장합니다. 세션 정보의 세부 사항은 백엔드 구현에 따라 다르지만 보다 일반적인 예를 들어 보겠습니다.
.service('Session', function () { this.create = function (sessionId, userId, userRole) { this.id = sessionId; this.userId = userId; this.userRole = userRole; }; this.destroy = function () { this.id = null; this.userId = null; this.userRole = null; }; return this; })
사용자가 로그인하면 해당 정보가 특정 위치에 표시되어야 합니다(예: 오른쪽 상단의 사용자 아바타 또는 그런 것) ). 이를 달성하려면 사용자 개체는 $scope 개체(전역적으로 호출할 수 있는 개체)에 의해 참조되어야 합니다. $rootScope가 확실한 첫 번째 선택이기는 하지만 $rootScope를 너무 많이 사용하지 않으려고 노력합니다(실제로 전역 이벤트 브로드캐스트에는 $rootScope만 사용합니다). 내가 선호하는 방식은 애플리케이션의 루트 노드나 적어도 DOM 트리보다 높은 위치에 컨트롤러를 정의하는 것입니다. 태그는 좋은 선택입니다.
<body ng-controller="ApplicationController"> ... </body>
ApplicationController는 애플리케이션의 전역 논리를 위한 컨테이너이자 Angular의 실행 메서드를 실행하기 위한 옵션입니다. 따라서 이는 $scope 트리의 루트에 있게 되며 다른 모든 범위는 이로부터 상속됩니다(격리 범위 제외). 이것은 currentUser 개체를 정의하기에 좋은 장소입니다.
.controller('ApplicationController', function ($scope, USER_ROLES, AuthService) { $scope.currentUser = null; $scope.userRoles = USER_ROLES; $scope.isAuthorized = AuthService.isAuthorized; $scope.setCurrentUser = function (user) { $scope.currentUser = user; }; })
실제로 currentUser 개체를 할당하지 않고 나중에 currentUser에 액세스할 수 있도록 범위가 지정된 속성을 초기화합니다. 안타깝게도 하위 범위의 currentUser에 새 값을 할당할 수는 없습니다. 그렇게 하면 섀도우 속성이 생성되기 때문입니다. 이는 기본 유형(문자열, 숫자, 부울, 정의되지 않음 및 null)을 참조 대신 값으로 전달한 결과입니다. 그림자 속성을 방지하려면 setter 함수를 사용해야 합니다. Angular 범위와 프로토타입 상속에 대해 자세히 알아보려면 범위 이해를 읽어보세요.
액세스 제어
신원 인증, 즉 액세스 제어는 실제로 AngularJS에는 존재하지 않습니다. 우리는 클라이언트 애플리케이션이기 때문에 모든 소스 코드는 사용자의 손에 있습니다. 사용자가 인증된 인터페이스를 얻기 위해 코드를 변조하는 것을 방지할 수 있는 방법은 없습니다. 우리가 할 수 있는 일은 컨트롤을 보여주는 것뿐입니다. 실제 인증이 필요한 경우 서버 측에서 인증을 수행해야 하지만 이는 이 문서의 범위를 벗어납니다.
요소 표시 제한
AngularJS에는 범위나 표현식을 기반으로 요소 표시 또는 숨기기를 제어하는 지시어(ngShow, ngHide, ngIf 및 ngSwitch)가 있습니다. 처음 두 개는