Lunes, 01 Agosto 2016 00:00

Login basado en Tokens con Satellizer - Angular JS

Escrito por 
Valora este artículo
(0 votos)

En este nuevo post veremos como realizar una autenticación a una determinada aplicación que nos proporciona un servicio rest, el cual nos devuelve un token que nos valida.

 

Para este ejemplo dispongo de  un Web Service  que nos autentica para poder usar determinados recursos, utilizo curl para este ejemplo, podriamos usar cualquier otra herramienta para poder probrar nuestros web services

1
2
curl --data "_username=admin&_password=password" http://localhost:8000/api/login_check

La salida de este WS  si los datos son correctos es la siguiente para mi caso

1
2
3
{
  "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJleHAiOjE0NzAxNzYzODcsInVzZXJuYW1lIjoiYWRtaW4iLCJpYXQiOiIxNDcwMDg5OTg3In0.StPGibXBvahrcutEjbM5-Pq0Dfgv766OsImiUcWoSffdePwkw890qeZnuAmdyz0tn6xZqahbJAGB0it4_CqMvH_q8qREsr97cmf_UsQEw3VHFAnvZel5d1FmfWA122JicKPaAi9xzP_GRW_3_gAruboKFR0MMaySTqNIMpZULr5yCxpRcBt0UgN8Jer-dzb_KrpSAJsMxvdJTxIqUZe-JjAeYceiRkQE1pPEUbDpS7ne5ZeUHD3YFf7QnNJzQmwVl9prBuMHHhelmehfJwu-odkfovEl-lvEtAKqmBeo03lGvRdUYWRVA3gcSJfd05vmt1zGG7TxGZl6elyGhRmyBfidDWjzuwStdRKoj8JWf_I34EjP7J_Vvd6yiNElriGi0zbA0jdmSg20EVsGDrbM5LvW0qPEW_bw7mSOmN2xjtpCIr3Q0CFE5NzamIR0pu80IS667ONtAxiy_Jng3h7x1VwGJY3N_jip-aeuXdbulq3kgoD1gpqXYpek8KkBGc8FJf_7ASw967Zk0b0QFg6JY3y_J4eZOtjJ3Z7wBw2_v3hRYbjVnx6l2gS9lC38lmIFw4cozifyrVo416FqEZYxALZ0EP5dG6NK7AhOXlS-5mnoM0jBbtdUDDnZfB8hDDagBcWfGLyMrQbTFoXGPQCdaGmVovgXTglA8xudwuWKVY4"
}

Que es el token creado y validado por la aplicación del lado del servidor (en este ejemplo estoy usando un WS rest en PHP con Symfony)

Bien ahora  procedemos a crear el Front End, utilizamos las siguientes librerias open source,

  1. Angular, para este post es necesario conocer sobre este maravilloso framework mvc de google
  2. Angular ui-router, nos porporciona un enrutamiento mas flexible a ng-route
  3. Boostrap para darle un poco de diseño
  4. Satellizer,  que es el fuerte de este post

 

A continuacion describo el archivo creado por Bower (resaltado con rojo), para saber mas de bower podemos ver este post http://compujuy.com.ar/blogs/item/39-bower-netbeans

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "name": "JWT-Angular",
  "version": "1.0.0",
  "main": "path/to/main.css",
  "ignore": [
    ".jshintrc",
    "**/*.txt"
  ],
  "dependencies": {
    "angular": "^1.5.8",
    "angular-ui-router": "^0.3.1",
    "satellizer": "^0.15.4",
    "bootstrap": "^3.3.7"
  },
  "devDependencies": {},
  "description": "Ejemplo JWT angular",
  "license": "MIT",
  "homepage": ""
}

 

Con este archivo  bastaria con ejecutar bower install y nos descarga las dependencias automaticamente.

Como mencionamos anteriormente Satellizer es el motivo de este post, podriamos  hacerlo nosotros manualmente, pero  no valdria la pena habiendo librerias que  ya lo tienen bien trabajado al tema (como diria un profe, no vamos a reinventar la rueda), Esta librería soporta autenticación mediante un usuario  y una contraseña a una api rest, por otra parte da soporte de proveedores OAuth como Facebook, Twitter, Google, Bitbucket, Yahoo entre otras.

Para saber mas de Satellizar podemos visitar  en github  su pagina oficial https://github.com/sahat/satellizer

Para este post utilizo netbeans, a continuacion muestro los archivos que contendra mi proyecto HTML 5 

Vamos al grano, a continuacion  se describe un servicio angular, que nos proporciona los metodos a usar para  un login

loginService.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
app.service('LoginService', ['$q', '$state', '$auth', '$http', '$timeout', 'baseUrl', function ($q, $state, $auth, $http, $timeout, baseUrl) {
        this.skipIfAuthenticated = function () {
            var defer = $q.defer();
            if ($auth.isAuthenticated()) {
                $timeout(function () {
                    $state.go("admin");
                });
                defer.reject();
            } else {
                defer.resolve();
            }
            return defer.promise;
        };
        this.redirectIfNotAuthenticated = function () {
            var defer = $q.defer();
            if ($auth.isAuthenticated()) {
                defer.resolve();
            } else {
                $timeout(function () {
                    $state.go("login");
                });
                defer.reject();
            }
            return defer.promise;
        };
        this.login = function (user, password) {
            var defer = $q.defer();
            var header = {headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }};
            var data = $.param({_username: user,
                _password: password});
            $auth.login(data, header).then(function (data) {
                defer.resolve(data);
            }).catch(function (response) {
                defer.reject(response);
            }).finally(function () {
            });
            return defer.promise;
        };
        this.logout = function () {
            var defer = $q.defer();
            $auth.logout().then(function (data) {
                defer.resolve(data);
            }, function (response) {
                defer.reject(response);
            }).finally(function () {
            });
            return defer.promise;
        };
    }]);

Breve descripcion de los metodos del servicio

skipIfAuthenticated : Salta si ya esta logeado la vista, es decir si quiero ir a la url del login, no deberia permitir si ya estamos logeados, entonces salta  y va a una determinada vista en este caso en la linea 6 va a la vista de admin

redirectIfNotAuthenticated: Redirecciona si no estamos logeados, por ejemplo si queremos acceder a una pagina protegida y no estamos autenticados, nos redirecciona a la vista de login, linea 20

login : Le pega al Web Service que nos autentica (http://localhost:8000/api/login_check) , le pasamos como parametros el usuario y contraseña, esto esta previamente configurado, lo veremos  mas adelante

logout : Nos desactiva el token del lado del servidor  y del lado del cliente nos elimina los datos guardados, en este caso (seria como cerrar la sesion).

A continuacion  el controlador 

loginController.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
app.controller('LoginCtrl', ['$scope', '$state', 'LoginService', function ($scope, $state, LoginService) {
        $scope.dataUser = {
            user: "",
            password: ""
        };
        $scope.mensaje = "";
        $scope.login = function () {
            $scope.mensaje = "";
            LoginService.login($scope.dataUser.user, $scope.dataUser.password).then(function () {
                $state.go("admin");
            }, function (response) {
                if (response.data.code === 401) {
                    $scope.mensaje = "Usuario o contraseña incorrectos";
                } else {
                    $scope.mensaje = "Hubo un error";
                }
            });
            ;
        };
        $scope.logout = function () {
            LoginService.logout().then(function () {
                $state.go("login");
            }, function (status) {
            });
            ;
        };
 
    }]);

Lo que hace el controlador es definir los datos del usuario  y los metodos que hacen uso del Servicio LoginService

Ahora las vistas, la siguiente seria la que solo podria ver el usuario autenticado

admin.tpl.html

1
2
<h1>Pagina protegida</h1>
<a href ng-click="logout();"  >Logout</a>

La vista de login

login.tpl.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="container" >
    <div class="row">
        <div class="col-sm-6 col-md-4 col-md-offset-4">
            <h1 class="text-center login-title">Login</h1>
            <div class="account-wall loadAjaxLogin">
                <form class="form-signin">
                    <input type="text" class="form-control" placeholder="Usuario" required autofocus ng-model="dataUser.user" >
                    <input type="password" class="form-control" placeholder="Contraseña" required ng-model="dataUser.password" >
                    <button class="btn btn-lg boton-0 btn-block" ng-click="login();" type="submit">
                        Login</button>
                </form>
            </div>
            <div  id="msgLogin" class="alert-danger">{{mensaje}}</div>
        </div>
    </div>
</div>

El index.html 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html ng-app="myapp">
    <head>
        <title>JWT-Ejemplo</title>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" media="screen">
    </head>
    <body>
        <div ui-view  style="width:100%; height:100%;"  >
 
        </div>
        <script src="bower_components/jquery/dist/jquery.min.js"></script>
        <script src="bower_components/angular/angular.min.js"></script>
        <script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
        <script src="bower_components/satellizer/dist/satellizer.min.js"></script>
        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
        <script src="js/app.js"></script>
        <script src="js/loginService.js"></script>
        <script src="js/loginController.js"></script>
        <script>
 index.html
        </script>
 
    </body>
</html>

 Asi queda el arbol del proyecto en Netbeans

 

 Estamos en condiciones de poder probar el simple proyecto realizado, en mi caso la  url del proyecto seria http://localhost:8383/JWT-Angular/index.html#/login

Si intentamos ingresar a la url protegina en este caso http://localhost:8383/JWT-Angular/index.html#/admin 

nos redireccionara a  la 'pantalla del login ya que satellizer no  tiene validado ningun token, si ingresamos datos incorrectos nos  muestra un mensaje  como en siguiente, ya que  el web service nos esta  respondiendo con

Status Code:  401 Unauthorized

 Si ingresamos  los datos correctos veremos que  nos redirecciona automaticamente a la pantalla de admin

A partir del logeo satellizer nos guarda la informacion en registros del navegador  y cada vez que se haga una peticion http, se enviara  el token en el header de cada peticion,

 

Una forma de hacerlo seria hacerlo manualmente cada  vez que se  requiera una peticion validada, pero deberiamos aprovechar estas librerias que  ya existen y  estan re  probadas. Espero que se de su ayuda... 

Visto 2158 veces Modificado por última vez en Sábado, 20 Agosto 2016 20:37

2 comentarios

Deja un comentario

Asegúrate de llenar la información requerida marcada con (*). No está permitido el código HTML. Tu dirección de correo NO será publicada.