web-dev-qa-db-fra.com

AngularJS: Exemple de base pour utiliser l'authentification dans une application à une seule page

Je suis nouveau sur AngularJS et j'ai parcouru leur tutoriel et j'ai eu une idée.

J'ai un backend pour mon projet prêt où chacun des noeuds finaux REST doit être authentifié.

Ce que je veux faire
a.) Je souhaite avoir une seule page pour mon projet http://myproject.com.
b.) Une fois que l'utilisateur a saisi l'URL dans le navigateur, qu'il soit connecté ou non, il se voit présenter une page d'accueil/vue ou une page de connexion/vue sous la même URL http://myproject.com .
c.) si un utilisateur n'est pas connecté, il remplit le formulaire et le serveur définit un USER_TOKEN dans la session. Ainsi, toutes les autres demandes adressées aux points de terminaison seront authentifiées sur la base de USER_TOKEN.

Mes confusions
a.) Comment puis-je gérer l'authentification côté client en utilisant AngularJS? J'ai vu ici et ici mais je ne comprenais pas comment les utiliser
b.) Comment puis-je présenter différentes vues à l'utilisateur en fonction de si l'utilisateur est connecté ou non sous la même URL http://myproject.com

J'utilise angular.js pour la toute première fois et je ne sais vraiment pas comment commencer. Tous les conseils et/ou ressources sont très appréciés.

99
daydreamer

J'aime l'approche et je l'ai mise en œuvre côté serveur sans rien faire d'authentification sur le front-end

Ma "technique" sur ma dernière application est… le client ne se soucie pas de Auth. Chaque élément de l'application nécessite d'abord une connexion. Le serveur sert toujours une page de connexion, sauf si un utilisateur existant est détecté dans la session. Si session.user est trouvé, le serveur envoie simplement index.html. Bam: -o

Recherchez le commentaire de "Andrew Joslin".

https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ

25
daydreamer

J'ai créé un repo github résumant cet article: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login dépôt Github

Plunker

Je vais essayer d'expliquer le mieux possible, en espérant pouvoir aider certains d'entre vous:

(1) app.js: Création de constantes d'authentification pour la définition d'application.

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) Service d'authentification: Toutes les fonctions suivantes sont implémentées dans le service auth.js. Le service $ http est utilisé pour communiquer avec le serveur pour les procédures d'authentification. Contient également des fonctions sur autorisation, c'est-à-dire si l'utilisateur est autorisé à effectuer une certaine action.

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) Session: Un singleton pour conserver les données de l'utilisateur. La mise en œuvre ici dépend de vous.

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) Contrôleur parent: Considérez ceci comme la fonction "principale" de votre application, tous les contrôleurs héritent de ce contrôleur et constituent la colonne vertébrale de l'authentification. de cette application.

<body ng-controller="ParentController">
[...]
</body>

(5) Contrôle d'accès: Pour refuser l'accès sur certaines routes, vous devez mettre en oeuvre 2 étapes:

a) Ajoutez les données des rôles autorisés à accéder à chaque route, sur le service $ stateProvider du routeur ui, comme indiqué ci-dessous (il en va de même pour ngRoute).

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b) Sur $ rootScope. $ on ('$ stateChangeStart') ajoutez la fonction pour empêcher le changement d'état si l'utilisateur n'est pas autorisé.

$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) Intercepteur d'authentification: Ceci est implémenté, mais ne peut pas être vérifié sur la portée de ce code. Après chaque demande $ http, cet intercepteur vérifie le code d'état. Si l'un des éléments ci-dessous est renvoyé, il diffuse un événement pour forcer l'utilisateur à se connecter à nouveau.

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);
        }
    };
} ]);

P.S. Un bogue lié à la saisie automatique des données de formulaire, comme indiqué dans le premier article, peut facilement être évité en ajoutant la directive incluse dans directives.js.

P.S.2 Ce code peut être facilement modifié par l'utilisateur afin de permettre la visualisation de différents itinéraires ou l'affichage de contenu non destiné à être affiché. La logique DOIT être implémentée côté serveur, c'est juste un moyen de montrer les choses correctement sur votre ng-app.

48
Alex Arvanitidis

J'ai répondu à une question similaire ici: Authentification AngularJS + API RESTful


J'ai écrit un module AngularJS pour serApp qui prend en charge les itinéraires protégés/publics, le reroutage lors de la connexion/déconnexion, les pulsations pour les contrôles d'état, stocke le jeton de session dans un cookie, les événements. , etc.

Vous pouvez soit:

  1. Modifiez le module et attachez-le à votre propre API, ou
  2. Utilisez le module avec serApp (une API de gestion des utilisateurs basée sur un nuage)

https://github.com/userapp-io/userapp-angular

Si vous utilisez UserApp, vous n'avez pas à écrire de code côté serveur pour le contenu utilisateur (plus que la validation d'un jeton). Prenez le cours sur Codecademy pour l'essayer.

Voici quelques exemples de son fonctionnement:

  • Comment spécifier quelles routes doivent être publiques et quelle route est le formulaire de connexion:

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
    $routeProvider.when('/home', {templateUrl: 'partials/home.html'});
    

    La route .otherwise() doit être définie sur l'endroit où vous souhaitez que vos utilisateurs soient redirigés après la connexion. Exemple:

    $routeProvider.otherwise({redirectTo: '/home'});

  • Formulaire de connexion avec traitement des erreurs:

    <form ua-login ua-error="error-msg">
        <input name="login" placeholder="Username"><br>
        <input name="password" placeholder="Password" type="password"><br>
        <button type="submit">Log in</button>
        <p id="error-msg"></p>
    </form>
    
  • Formulaire d'inscription avec traitement des erreurs:

    <form ua-signup ua-error="error-msg">
      <input name="first_name" placeholder="Your name"><br>
      <input name="login" ua-is-email placeholder="Email"><br>
      <input name="password" placeholder="Password" type="password"><br>
      <button type="submit">Create account</button>
      <p id="error-msg"></p>
    </form>
    
  • Lien de déconnexion:

    <a href="#" ua-logout>Log Out</a>

    (Termine la session et redirige vers la route de connexion)

  • Propriétés de l'utilisateur d'accès:

    Les propriétés utilisateur sont accessibles via le service user, par exemple: user.current.email

    Ou dans le modèle: <span>{{ user.email }}</span>

  • Cacher les éléments qui ne devraient être visibles que lors de la connexion:

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • Affiche un élément en fonction des autorisations:

    <div ua-has-permission="admin">You are an admin</div>

Et pour vous authentifier auprès de vos services back-end, utilisez simplement user.token() pour obtenir le jeton de session et envoyez-le avec la demande AJAX. Sur le back-end, utilisez le API UserApp (si vous utilisez UserApp) pour vérifier si le jeton est valide ou non.

Si vous avez besoin d'aide, faites le moi savoir!

14

Dans angularjs, vous pouvez créer la partie interface utilisateur, le service, les directives et toutes les parties angularjs qui représentent l'interface utilisateur. C'est une technologie intéressante sur laquelle travailler.

Comme toute personne débutant dans cette technologie et voulant authentifier "l'utilisateur", je suggère de le faire avec la puissance de c # web api. Pour cela, vous pouvez utiliser la spécification OAuth qui vous aidera à créer un mécanisme de sécurité renforcé pour authentifier l'utilisateur. Une fois que vous avez créé WebApi avec OAuth, vous devez appeler cette API pour le jeton:

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

et une fois que vous avez obtenu le jeton, vous demandez les ressources à angularjs à l'aide de Token et accédez à la ressource sécurisée dans Web Api avec la spécification OAuth.

S'il vous plaît jeter un oeil dans l'article ci-dessous pour plus d'aide: -

http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/

2
Gurupreet

Je pense que chaque réponse JSON doit contenir une propriété (par exemple {authentifié: false}) et que le client doit la tester à chaque fois: si false, le contrôleur/service Angular "se redirigera" vers la page de connexion .

Et que se passe-t-il si l'utilisateur intercepte JSON et modifie le booléen en True?

Je pense que vous ne devriez jamais compter sur le côté client pour faire ce genre de choses. Si l'utilisateur n'est pas authentifié, le serveur doit simplement rediriger vers une page de connexion/d'erreur.

1
Doum
var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 
0
Nver Abgaryan