Heim > Web-Frontend > js-Tutorial > Detaillierte Codebeispiele zur Verwendung von AngularJS zur Authentifizierung

Detaillierte Codebeispiele zur Verwendung von AngularJS zur Authentifizierung

伊谢尔伦
Freigeben: 2017-07-20 10:46:10
Original
1593 Leute haben es durchsucht

Identitätsauthentifizierung

Die gebräuchlichste Methode zur Identitätsauthentifizierung ist die Verwendung eines Benutzernamens (oder einer E-Mail-Adresse) und eines Passworts zur Anmeldung. Dies bedeutet die Implementierung eines Anmeldeformulars, damit sich Benutzer mit ihren persönlichen Daten anmelden können. Das Formular sieht so aus:

<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>
Nach dem Login kopieren

Da es sich um ein Angular-basiertes Formular handelt, verwenden wir die ngSubmit-Direktive, um die Funktion beim Hochladen des Formulars auszulösen. Beachten Sie, dass wir die persönlichen Informationen an die Funktion zum Hochladen des Formulars übergeben, anstatt das Objekt $scope.credentials direkt zu verwenden. Dies erleichtert den Unit-Test der Funktion und verringert die Kopplung der Funktion an den aktuellen Controller-Bereich. Der Controller sieht so aus:

.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);
})
Nach dem Login kopieren

Wir bemerken, dass es hier an tatsächlicher Logik mangelt. Dieser Controller ist so aufgebaut, dass er die Authentifizierungslogik vom Formular entkoppelt. Es ist eine gute Idee, so viel Logik wie möglich aus unserem Controller zu extrahieren und alles in Dienste zu packen. Der Controller von AngularJS sollte nur die Objekte im $scope verwalten (durch Überwachung oder manuelle Bedienung), anstatt zu viele übermäßig schwere Aufgaben zu übernehmen.

Benachrichtigung über Sitzungsänderungen

Die Identitätsauthentifizierung wirkt sich auf den Status der gesamten Anwendung aus. Aus diesem Grund verwende ich lieber Ereignisse (mit $broadcast), um Benutzersitzungsänderungen zu benachrichtigen. Es ist eine gute Idee, alle Ereigniscodes zu definieren, die in einem Mittelweg verwendet werden können. Dazu verwende ich gerne Konstanten:

.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;
})
Nach dem Login kopieren

Eine gute Eigenschaft von Konstanten ist, dass sie wie Dienste nach Belieben an anderen Stellen eingefügt werden können. Dadurch können Konstanten von unserem Unit-Test leicht aufgerufen werden. Mit Konstanten können Sie sie später auch einfach umbenennen, ohne eine Reihe von Dateien ändern zu müssen. Der gleiche Trick funktioniert mit Benutzerrollen:

.constant(&#39;USER_ROLES&#39;, {
 all: &#39;*&#39;,
 admin: &#39;admin&#39;,
 editor: &#39;editor&#39;,
 guest: &#39;guest&#39;
})
Nach dem Login kopieren

Wenn Sie Redakteuren und Administratoren die gleichen Berechtigungen geben möchten, ändern Sie einfach „Editor“ in „Administrator“.

Der AuthService

Logik im Zusammenhang mit der Identitätsauthentifizierung und -autorisierung (Zugriffskontrolle) lässt sich am besten im selben Dienst platzieren:

.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;
})
Nach dem Login kopieren

Um mich weiter von den Bedenken der Identitätsauthentifizierung zu distanzieren, verwende ich einen anderen Dienst (ein Singleton-Objekt im Service-Stil), um die Sitzungsinformationen des Benutzers zu speichern. Die Details der Sitzungsinformationen hängen von der Backend-Implementierung ab, aber ich gebe ein allgemeineres Beispiel:

.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;
})
Nach dem Login kopieren

Sobald sich der Benutzer anmeldet, sollten seine Informationen an einigen Stellen angezeigt werden (z. B. Benutzer-Avatar oder so). in der oberen rechten Ecke). Um dies zu erreichen, muss das Benutzerobjekt durch das $scope-Objekt referenziert werden, vorzugsweise eines, das global aufgerufen werden kann. Obwohl $rootScope die offensichtliche erste Wahl ist, versuche ich, $rootScope nicht zu häufig zu verwenden (eigentlich verwende ich $rootScope nur für globale Ereignisübertragungen). Am liebsten definiere ich dazu einen Controller am Stammknoten der Anwendung oder an einer anderen Stelle, die zumindest höher als der DOM-Baum liegt. Tags sind eine gute Wahl:

<body ng-controller="ApplicationController">
 ...
</body>
Nach dem Login kopieren

ApplicationController ist ein Container für die globale Logik der Anwendung und eine Option zum Ausführen der Ausführungsmethode von Angular. Daher befindet es sich im Stammverzeichnis des $scope-Baums und alle anderen Bereiche erben von ihm (mit Ausnahme des Isolationsbereichs). Dies ist ein guter Ort, um das currentUser-Objekt zu definieren:

.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;
 };
})
Nach dem Login kopieren

Wir weisen das currentUser-Objekt nicht wirklich zu, wir initialisieren lediglich die bereichsbezogenen Eigenschaften, damit auf currentUser später zugegriffen werden kann. Leider können wir „currentUser“ im untergeordneten Bereich nicht einfach einen neuen Wert zuweisen, da dadurch eine Schatteneigenschaft erstellt würde. Dies ist das Ergebnis der Übergabe primitiver Typen (Strings, Zahlen, Boolesche Werte, undefiniert und null) nach Wert statt nach Referenz. Um Schatteneigenschaften zu verhindern, müssen wir Setter-Funktionen verwenden. Wenn Sie mehr über Angular-Bereiche und prototypische Vererbung erfahren möchten, lesen Sie Understanding Scopes.

Zugriffskontrolle

Identitätsauthentifizierung, also Zugriffskontrolle, gibt es in AngularJS eigentlich nicht. Da wir eine Client-Anwendung sind, liegt der gesamte Quellcode in den Händen des Benutzers. Es gibt keine Möglichkeit, Benutzer daran zu hindern, den Code zu manipulieren, um eine authentifizierte Schnittstelle zu erhalten. Wir können nur die Steuerelemente anzeigen. Wenn Sie eine echte Authentifizierung benötigen, müssen Sie diese serverseitig durchführen, aber das würde den Rahmen dieses Artikels sprengen.

Anzeige von Elementen einschränken

AngularJS verfügt über Anweisungen zum Steuern des Ein- oder Ausblendens von Elementen basierend auf Umfang oder Ausdrücken: ngShow, ngHide, ngIf und ngSwitch. Die ersten beiden verbergen das Element mithilfe eines