|
June 8, 2017
|

AngularJS, rotas e JWT

Introdução

No post anterior, Adicionando segurança a uma aplicação java com JWT, foi desenvolvida uma camada de segurança no lado servidor, para proteger a API da aplicação de Cadastro de Usuários. Entretanto, ficou faltando desenvolver as modificações necessárias do lado cliente para consumir os serviços protegidos.

Para que isso seja possível, construiremos uma tela de login e acrescentaremos um sistema de rotas na aplicação de exemplo. Vamos tentar ser o mínimo intrusivos para que a regra de negócio que já estava funcionando não precise de alteração, igual ao que foi desenvolvido no lado servidor.

Vamos ao código!

Rotas

O AngularJS fornece todas as ferramentas que necessitamos para desenvolver uma Single Page Application. Em aplicação de página única, o roteamento é extremamente importante. Quando o usuário navegar no sistema, queremos que ele tenha a impressão de que está em um site normal, mas sem a necessidade de carregamento de toda a tela ao trocar de página.

É por esse motivo que vamos adicionar rotas a aplicação utilizando o framework Ui Router. O motivo de sua escolha, em vez do ngRoute que o AngularJS fornece nativamente, é que ele provê meios da navegação ser feita através de estados e não somente por URLs.

Para iniciar o uso do ui-router, adicionaremos a dependência javascript ao nosso index: <script src=”//unpkg.com/angular-ui-router/release/angular-ui-router.min.js”></script>. Em seguida, registraremos a utilização da biblioteca por meio da adição do módulo:

angular.module('registration', ['ui.router'])

Para finalizar a configuração, precisamos mover o código referente ao cadastro do usuário do index.html e adicioná-lo ao novo arquivo user.html. Depois, no lugar do código modificado, será necessário colocar a diretiva ui-view, que faz parte do ui-router. Essa diretiva será a responsável por permitir que o html das rotas seja introduzido no index.html sem a necessidade de atualizar toda a página. O index ficará da seguinte forma:


<div class="container">
    <div class="row">
        <div class="col-md-offset-2 col-md-8">
            <div class="content" ui-view> </div>
        </div>
    </div>
</div>

...
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>


Configurando as rotas

Feito isso, a configuração das rotas se dá por intermédio do service $stateProvider.state. Criaremos duas rotas para a aplicação, uma para a tela de login e outra para o cadastro de usuário:

.config(function ($stateProvider, $urlRouterProvider) {
    var login = {
        name: 'login',
        url: '/login',
        templateUrl: 'login.html',
        controller: 'LoginController'
    };

    var user = {
        name: 'user',
        url: '/user',
        templateUrl: 'user.html',
        controller: 'UserController',
        resolve:{
            userLogged: function($state, $rootScope){
                if(!$rootScope.me){
                    console.log('Not authorized!!')
                    $state.go('login');
                }
            }
        }
    };

    $urlRouterProvider.otherwise('/login');

    $stateProvider.state(login);
    $stateProvider.state(user);
})

No código acima, temos o registro das rotas login e user. Basicamente, é necessário realizar a seguinte configuração:

  • name: é o nome do estado que representa a rota;
  • url: é a URL da rota;
  • templateUrl: o arquivo que contém o html a ser exibido;
  • controller: o controller que será usado pelo html;
  • resolve: utilizado para pré-carregar dados na rota. No exemplo, utilizamos para verificar se o usuário possui permissão de acessar a rota user, caso não possua, é redirecionado para a tela de login.

Resgatando o token e adicionando ao cabeçalho

Com as rotas configuradas, precisamos enviar as credenciais do usuário para o servidor e receber o token de volta. Para isso, precisaremos de um formulário de login (login.html) e de um controlador para gerenciá-lo (LoginController):

.controller('LoginController', function ($scope, $http, $rootScope, $state) {

    $scope.credentials = {username: '', password: ''};

    $scope.login = function () {
        $http.post('api/login', $scope.credentials).then(function (response) {
            $rootScope.me = response.data;
            $http.defaults.headers.common['Authorization'] = $rootScope.me.token;
            $state.go('user');
        }, function (error) {
            alert('Error authentication...');
            console.log(error);
        });
    }
})

Quando o formulário de login for submetido, o método login será chamado. Percebam que ele fará um post na URL api/login, conforme vimos no post passado. Como resposta, o servidor enviará o token. Nesse ponto temos um detalhe importante: notem que na linha $http.defaults.headers.common[‘Authorization’] = $rootScope.me.token estamos informando ao service $http que o token será adicionado ao cabeçalho de todas as requisições, por padrão. Assim, não precisaremos adicioná-lo manualmente sempre que uma requisição for feita para o servidor. Lembrem, a ideia é ser o mínimo intrusivo.

Outro ponto relevante, é o uso do $state.go. Ele é usado para mudar o estado da rota. Ou seja, quando o login for realizado com sucesso, a rota será alterada para user e a tela será alterada para o formulário de cadastro que já possuíamos.

Agora, temos uma aplicação que autentica no servidor e consegue consumir a API sem maiores modificações. Bem simples, não?

Há muito mais detalhes que não foram exemplificados neste post, como, por exemplo, o uso de eventos do ui-router. Com eles, podemos criar  uma configuração genérica de controle de acesso e remover essa configuração do “resolve” que foi adicionado na rota do cadastro do usuário.

Além disso, se a página for recarregada o token será perdido, exigindo que o usuário seja autenticado novamente. Para resolver esse problema, é necessário armazenar o token de alguma forma. Por exemplo, no Storage do browser.

O código fonte do exemplo está no nosso github!

Se você curtiu este post, compartilhe e marque seus amigos.

Abraços e até a próxima!

Comments

More articles

Afinal, é possível criar app sem saber programação?

November 16, 2018

Como transformar um website em aplicativo?

November 14, 2018

Aplicativos: O que conhecer antes de criar um

November 13, 2018

É possível instalar aplicativos Android no Windows?

November 9, 2018