1. Code
  2. Coding Fundamentals
  3. Authentication

Аутентификация Angular с JWT

Scroll to top

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

Безопасность является важной частью каждого веб-приложения, и разработчики должны убедиться, что они разрабатывают приложения с безопасной аутентификацией. В этом руководстве вы узнаете, как реализовать аутентификацию на основе JWT в приложениях Angular с помощью простого сервера Express.

Полный код можно найти в нашем репозитории GitHub. Приложение, которое мы будем создавать, будет выглядеть так:

Final LookFinal LookFinal Look

Концепция веб-токенов JSON

JSON Web Token (JWT) - это в основном объект, представленный тремя строками, которые используются для передачи пользовательской информации. Три строки, разделенные точками:

  • заголовок
  • полезная нагрузка
  • подпись

Когда пользователь входит на любую веб-страницу со своим именем пользователя и паролем, сервер аутентификации обычно создает и отправляет обратно JWT. Затем этот JWT передается вместе с последующими вызовами API на сервер. JWT остается в силе, пока не истечет срок его действия или пользователь не выйдет из приложения.

Этот процесс может быть проиллюстрирован на диаграмме ниже.

JWT authorization flowJWT authorization flowJWT authorization flow

Файлы cookie и локальное хранилище

Мы будем использовать локальное хранилище для хранения токенов. Локальное хранилище - это средство, с помощью которого данные хранятся локально и могут быть удалены только через JavaScript или путем очистки кэша в браузере. Данные, хранящиеся в локальном хранилище, могут сохраняться очень долго. С другой стороны, файлы cookie - это сообщения, которые отправляются с сервера в браузер и имеют ограниченное хранилище.

Создание Express сервера

Мы начнем с создания внутреннего сервера, который будет иметь следующие конечные точки:

  • POST <webservice>/login
  • POST <webservice>/profile

Давайте начнем с создания каталога для приложения Express, а затем запустим команду npm init, чтобы установить необходимые файлы для проекта.

1
mkdir server
2
cd server
3
npm init

Затем создайте файл server.js и установите модули: express, jsonwebtoken, cors и bodyParser.

1
touch server.js
2
npm install express jsonwebtoken cors bodyParser –save

Теперь откройте server.js и начните с импорта модулей.

1
// server.js

2
const cors = require('cors');
3
const bodyParser = require('body-parser');
4
const jwt = require('jsonwebtoken');
5
const express = require('express');

Затем создайте приложение Express и определите секретный ключ, который будет использоваться для кодирования и декодирования данных пользователя.

1
//CREATE EXPRESS APP

2
const app = express();
3
app.use(cors());
4
app.use(bodyParser.json());
5
6
// DECLARE JWT-secret

7
const JWT_Secret = 'your_secret_key';

Мы не будем использовать базу данных для этого примера. Тем не менее, концепции были бы похожи, если бы вы писали правильный сервер с поддержкой базы данных.

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

1
var testUser = { email: 'kelvin@gmai.com', password: '1234'};

Последний шаг - создание маршрутов для аутентификации пользователя.

1
app.post('/api/authenticate', (req, res) => {
2
3
  if (req.body) {
4
    var user = req.body;
5
    console.log(user)
6
7
    if (testUser.email===req.body.email && testUser.password === req.body.password) {
8
      var token = jwt.sign(user, JWT_Secret);
9
      res.status(200).send({
10
        signed_user: user,
11
        token: token
12
      });
13
    } else {
14
      res.status(403).send({
15
        errorMessage: 'Authorisation required!'
16
      });
17
    }
18
  } else {
19
    res.status(403).send({
20
      errorMessage: 'Please provide email and password'
21
    });
22
  }
23
24
});

Давайте разберем код для маршрута выше.

Сначала мы проверяем, есть ли какие-либо данные в теле запроса. Если данные не найдены, мы предлагаем пользователю ввести некоторые данные. В случае, когда пользователь предоставил правильные данные, мы сравниваем их с данными из testUser и, если они совпадают, мы используем идентификатор пользователя, чтобы сгенерировать уникальный токен и отправить ответ пользователю.

Наконец, мы создаем конечную точку для запуска приложения.

1
app.listen(5000, () => console.log('Server started on port 5000'));

Наш бэкэнд теперь готов, и вы можете протестировать его с помощью Postman или CURL и посмотреть, какие данные будут возвращены пользователю.

Создайте приложение Angular

Наше приложение Angular будет содержать следующие страницы:

  • Главная страница - эта страница будет содержать ссылки на страницы входа и профиля.
  • Логин - на этой странице пользователь введет свой адрес электронной почты и пароль, которые будут отправлены на сервер для аутентификации. Если учетные данные верны, то будет возвращен токен JWT, и пользователь будет перенаправлен на страницу профиля.
  • Профиль - это защищенная страница, доступ к которой может получить только пользователь с действительным токеном.

Создайте приложение Angular и создайте компоненты Login и Profile, как показано ниже:

1
ng new angular6jwt
2
cd angular6jwt
3
ng g component Login
4
ng g component Profile

Затем добавьте код для домашней страницы в app.component.html.

1
<!--The content below is only a placeholder and can be replaced.-->
2
<div style="text-align:center">
3
<ul>
4
  <li><a class="nav-link" routerLink="/" routerLinkActive="active">Home</a>  </li>
5
  <li><a class="nav-link" routerLink="profile" routerLinkActive="active">Profile</a>  </li>
6
  <li style="float:right" > <a class="nav-link"  style="float:right" routerLink="login" routerLinkActive="active">Login</a> </li>
7
  <li style="float:right" > <a class ="nav-link" (click)="logout()" href="#">Logout</a></li>
8
</ul>
9
<div class="text-center">
10
  <p>
11
    Angular 6 Authentication with JWT Tutorial
12
  </p>
13
</div>
14
<router-outlet></router-outlet>
15

Затем импортируйте RouterModule и определите маршруты в app.module.ts.

1
import { RouterModule } from '@angular/router';
2
3
4
@NgModule({
5
  declarations: [
6
    AppComponent,
7
    LoginComponent,
8
    ProfileComponent
9
  ],
10
  imports: [
11
    BrowserModule,
12
    RouterModule,
13
    FormsModule,
14
    RouterModule.forRoot([
15
      { path: '', redirectTo: '/', pathMatch: 'full' },
16
      { path: 'login', component: LoginComponent },
17
      { path: 'profile', component: ProfileComponent }
18
      
19
    
20
]),
21
  ],
22
  providers: [],
23
  bootstrap: [AppComponent]
24
})
25
export class AppModule { }

Создаем страницу входа

Страница входа будет содержать два поля ввода для адреса электронной почты и пароля, а также кнопку отправки, как показано ниже:

1
<h3>Login</h3>
2
<div>
3
  <div class="spacer">
4
    <label for="Email">Email</label>
5
    <input type="text" placeholder="Email" [(ngModel)]="email">
6
  </div>
7
  <div class="spacer">
8
    <label for="password">Password</label>
9
    <input type="password" placeholder="password" [(ngModel)]="password" class="form-control"/>
10
  </div>
11
  <div class="spacer">
12
    <button  type="submit" (click)="Login()">Login</button>
13
  </div>
14
</div>

Создаем страницу профиля

Страница профиля будет просто сообщением, как показано ниже:

1
<p>
2
  If you can see this page, you are logged in!
3
</p>

Авторизация с JWT в Angular

Мы начнем с создания сервиса Auth, который облегчит проверку ввода пользователя и взаимодействия с сервером.

1
// Create authentication service named Auth

2
ng g service Auth

Это создает два файла, но в основном нас заинтересует файл auth.service.ts, в который мы напишем весь код, взаимодействующий с сервером. Мы начнем с определения REST API и токена, как показано ниже:

1
export class AuthService {
2
3
  api = 'https://localhost:3000/api';
4
  token;
5
6
}

Далее мы напишем код, который выполняет POST-запрос к серверу с учетными данными пользователя. Здесь мы делаем запрос к API - если он успешен, мы сохраняем токен в localStorage и перенаправляем пользователя на страницу профиля.

1
import { Injectable } from '@angular/core';
2
import { HttpClientModule, HttpClient } from '@angular/common/http';
3
import { Router } from '@angular/router';
4
5
@Injectable({
6
  providedIn: 'root'
7
})
8
9
export class AuthService {
10
11
  uri = 'http://localhost:5000/api';
12
  token;
13
14
  constructor(private http: HttpClient,private router: Router) { }
15
  login(email: string, password: string) {
16
    this.http.post(this.uri + '/authenticate', {email: email,password: password})
17
    .subscribe((resp: any) => {
18
    
19
      this.router.navigate(['profile']);
20
      localStorage.setItem('auth_token', resp.token);
21
     
22
      })
23
      );
24
      
25
    }
26
27
}

Мы также определяем функции входа и выхода из системы, как показано ниже.

1
logout() {
2
    localStorage.removeItem('token');
3
  }
4
5
  public get logIn(): boolean {
6
    return (localStorage.getItem('token') !== null);
7
  }
  • logout - очищает токен от локального хранилища
  • logIn - возвращает логическое свойство, которое определяет, аутентифицирован ли пользователь

Затем мы обновляем свойство logIn на домашней странице, как показано.

1
<ul>
2
  <li><a class="nav-link" routerLink="/" routerLinkActive="active">Home</a>  </li>
3
  <li><a class="nav-link" routerLink="profile" routerLinkActive="active" *ngIf="authService.logIn">Profile</a>  </li>
4
  <li style="float:right" > <a class="nav-link"  style="float:right" routerLink="login" routerLinkActive="active" *ngIf="!authService.logIn">Login</a> </li>
5
  <li style="float:right" > <a class ="nav-link" (click)="logout()" href="#" *ngIf="authService.logIn">Logout</a>  </li>
6
</ul>

Ответ на пользовательские события

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

Мы напишем функцию, которая будет прослушивать события щелчка со страницы входа в систему, а затем передавать значения в AuthService для аутентификации пользователя. Обновите файл login.component.ts, чтобы он выглядел следующим образом:

1
import { Component, OnInit } from '@angular/core';
2
import { Router, ActivatedRoute } from '@angular/router';
3
4
import { AuthService } from '../auth.service';
5
6
@Component({
7
  selector: 'app-login',
8
  templateUrl: './login.component.html',
9
  styleUrls: ['./login.component.css']
10
})
11
export class LoginComponent implements OnInit {
12
  email = '';
13
  password = '';
14
  
15
  constructor(private authService: AuthService) {
16
    
17
  }
18
  Login() {
19
  console.log("you are logging in")
20
  this.authService.login(this.email, this.password)
21
  
22
  }
23
24
  ngOnInit() { }
25
}

Теперь, если вы запустите ng serve и перейдете по адресу http://localhost:4200, вы можете протестировать свое приложение.

1
ng serve

Нажмите на ссылку для входа и введите учетные данные пользователя. Помните, действительные учетные данные определены в приложении Express. Теперь, когда вы нажмете кнопку входа в систему, вы будете перенаправлены на страницу профиля.

Заключение

Из этого руководства вы узнали, как начать работу с аутентификацией JWT в Angular. Теперь вы можете проходить аутентификацию и авторизацию с помощью JWT в ваших приложениях Angular. Есть много аспектов JWT, которые не были рассмотрены в этом руководстве - посмотрите, можете ли вы изучить некоторые из них самостоятельно!

Обратите внимание, что это руководство было написано для Angular 6, но те же концепции должны работать с Angular 2 или Angular 4.