인증을 위해 AngularJS를 사용하는 방법에 대한 자세한 코드 예제

伊谢尔伦
풀어 주다: 2017-07-20 10:46:10
원래의
1563명이 탐색했습니다.

신원 인증

가장 일반적인 신원 인증 방법은 사용자 이름(또는 이메일)과 비밀번호를 사용하여 로그인하는 것입니다. 이는 사용자가 자신의 개인 정보를 사용하여 로그인할 수 있도록 로그인 양식을 구현하는 것을 의미합니다. 양식은 다음과 같습니다.

<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(&#39;LoginController&#39;, function ($scope, $rootScope, AUTH_EVENTS, AuthService) {
 $scope.credentials = {
  username: &#39;&#39;,
  password: &#39;&#39;
 };
 $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(&#39;AUTH_EVENTS&#39;, {
 loginSuccess: &#39;auth-login-success&#39;,
 loginFailed: &#39;auth-login-failed&#39;,
 logoutSuccess: &#39;auth-logout-success&#39;,
 sessionTimeout: &#39;auth-session-timeout&#39;,
 notAuthenticated: &#39;auth-not-authenticated&#39;,
 notAuthorized: &#39;auth-not-authorized&#39;
})
로그인 후 복사

상수의 가장 큰 특징은 서비스와 마찬가지로 마음대로 다른 곳에 주입할 수 있다는 것입니다. 이를 통해 단위 테스트에서 상수를 쉽게 호출할 수 있습니다. 또한 상수를 사용하면 나중에 많은 파일을 변경하지 않고도 쉽게 이름을 바꿀 수 있습니다. 사용자 역할에도 동일한 방법이 적용됩니다.

.constant(&#39;USER_ROLES&#39;, {
 all: &#39;*&#39;,
 admin: &#39;admin&#39;,
 editor: &#39;editor&#39;,
 guest: &#39;guest&#39;
})
로그인 후 복사

편집자와 관리자에게 동일한 권한을 부여하려면 간단히 'editor'를 'admin'으로 변경하면 됩니다.

The AuthService

인증 및 권한 부여(액세스 제어)와 관련된 로직은 동일한 서비스에 배치하는 것이 가장 좋습니다.

.factory(&#39;AuthService&#39;, function ($http, Session) {
 var authService = {};

 authService.login = function (credentials) {
  return $http
   .post(&#39;/login&#39;, 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(&#39;Session&#39;, 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(&#39;ApplicationController&#39;, 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)가 있습니다. 처음 두 개는