11.25.2016

Коротко о логике авторизации и роутинге используя Angular 2

Для решения данного вопроса вполне достаточно документации на официальном сайте Angular 2

Однако!

В разделе описано много больше информации и если английский текст вы воспринимаете медленно, то данная небольшая статья поможет быстро вникнуть в суть происходящего.

А,  я лишь хочу обрисовать общую логику процесса и некоторые моменты авторизации так, чтобы вы (и я) могли максимально быстро настроить роутинг для своего проекта.

Простая навигация по ссылкам не самый интересный вариант с точки зрения реального применения. В реальности мы имеем приватную и публичную часть приложения. А иногда, только приватную, которая доступна только после авторизации. Весь роутинг после авторизации будет представлять собой самый простой вид роутинга т.е. написал путь и привязал к нему компонент который будет отображаться.

Мне удобно представлять "картину целиком" прежде чем приступать к работе.

Итак! У нас будет главный роутинг приложения, и модуль роутинга для приватной части. В роутинге приватной части используются дочерние пути. Дочерние пути будут защищаться при помощи сервисов авторизации. Авторизироваться можно будет при помощи компонета входа (login). Сервисы авторизации авторизируют пользователя и запоминают состояние.

Итого:
  • Главный роутинг
  • Дочерний роутинг приватной части
  • Сервисы авторизации
  • Компонент входа (форма входа)

Теперь логика процесса авторизации. Пользователь заходит на главную страницу сайта, главный роутнг отправляет его на приватную часть сайта. Пути приватной части сайта обрабатывает роутинг приватной части. Для проверки нужно ли отображать дочерние пути он использует сервис авторизации. Если сервис подтвердит, что у пользователя есть права то роутинг обработает запрос к дочерним путям. Если нет, то будет вызван роут для несуществующего пути (404 страница). Если роутинг приватной части не обрабатывает 404 ошибку то, это попытается сделать главный роутинг. Если и он не справится то выпадет ошибка:
Unhandled promise rejection
Error: Permission denied to access property "rejection"
Поэтому сервис авторизации в случае если пользователь не авторизован должен сам направить его на нужный маршрут по которому запрос обработает модуль входа. А так же не забывайте ставить обработку несуществующего пути:
{
    path: "**",
    component: NotFoundComponent
}

Теперь по сути и с кусками кода.
Пользователь заходи на главную страницу и это обрабатывает главный роутинг:
const routes: Routes = [
    {
        path: '',
        redirectTo: '/panel',
        pathMatch: 'full'    },
    {
        path: 'login',
        component: LoginComponent
    },
    {
        path: "**",
        component: NotFoundComponent
    }
];
Так же не забываейте, что для роутинга приватной части нужен свой тег
<router-outlet></router-outlet>который будет находиться в главном компоненте приватной части, так же как и для всего приложения он находится в app.component.

Пользователь перенаправляется на приватную часть сайта, это обрабатывает роутинг приватной части:
const routes: Routes = [
    {
        path: 'panel',
        canActivate: [AuthGuard],
        component: AdminComponent,
        children: [
            {
                path: '',
                canActivateChild: [AuthGuard],
                children: [
                    {
                        path: '',
                        component: DashboardComponent,
                    },
                    {
                        path: 'dashboard',
                        component: DashboardComponent
                    },
                    {
                        path: 'logs',
                        component: LogsComponent
                    },
                    {
                        path: 'configs',
                        component: ConfigsComponent
                    }
                ]
            }
        ]
    }
];
Для проверки авторизации роутинг использует AuthGuard подключенный в роуты такой строчкой:
canActivate: [AuthGuard],
Сам сервис авторизации должен реальзовывать два метода canActivate и canActivateChild. Выглядит следующим образом:
import { Injectable }       from '@angular/core';
import {
    CanActivate, Router,
    ActivatedRouteSnapshot,
    RouterStateSnapshot,
    CanActivateChild
}                           from '@angular/router';
import { AuthService }      from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {

    canActivate(): boolean {
        return this.checkLogin();
    }

    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.canActivate();
    }
    checkLogin(url: string): boolean {
        // используем сервис this.authService 
        // чтобы проверить авторизован ли пользователь 
        // выполнить редирект на компонент входа можно тут
    }
}
Для выполнения редиректа нужно подключать модуль Router
import { Router } from '@angular/router';
Добавлять его в класс который будет выполнять редирект
constructor(
    private authService: AuthService,
    private router: Router
) {}
И вызывать редирект следующим образом:
this.router.navigate(['/login']);
Компонент входа (/login) использует сервис авторизации authService, который может иметь любую логику на ваше усмотрение, например в таком виде:
import { Injectable } from '@angular/core';

@Injectable()
export class AuthService {
    isLoggedIn: boolean = false;

    // store the URL so we can redirect after logging in    redirectUrl: string;

    login(): Observable<boolean> {
        return this.isLoggedIn = true;
    }

    logout(): void {
        this.isLoggedIn = false;
    }
}

Остальное и более подробно читайте в официальной документации:
https://angular.io/docs/ts/latest/guide/router.html
Angular 2 Router:
https://vsavkin.com/angular-2-router-d9e30599f9ea